What is GigaWallet?

The GigaWallet Logo

Dogecoin GigaWallet is a backend service which provides a convenient integration API for platforms such as online shops, exchanges, social media platforms etc, to accept and transact Dogecoin on behalf of their users.

The purpose of the GigaWallet is to promote the rapid uptake of Dogecoin as a payment option, by taking the complexity and risk out of integrating Dogecoin payments into business.

Static Badge

It's dangerous to go alone, take this? Maybe!

⚠️ Note: GigaWallet is a software-engineering component for anyone looking to integrate Dogecoin into their product, this is not a user-facing Dogecoin wallet. If you are a user looking for a dogecoin wallet you can search the wallet index on the dogecoin.com website.

dangerous to go alone

It is expected that you are a comfortable with managing server infrastructure and integrating with REST APIs. GigaWallet is a service that must be deployed behind a firewall that protects it's sensitive APIs from the public internet, to which you will integrate your public-facing systems.

Effort has been taken to create a system which integrates with your platform, and so the APIs for Accounts all require a foreignID which represents the account from your system.

GigaWallet manages it's own database to track HD wallets, Invoices, UTXOs and other data it needs, however it is not a general-purpose shopping cart or user management system, it is expected that you will provide what you need on your side to create the magic ✨ you have in mind, good luck adventurer!

Basic Concepts

GigaWallet has been designed as a drop-in solution for anyone who needs to accept Dogecoin and respond in a timely manner when payment arrives.

From individual stores who need a Dogecoin checkout solution to global social media networks with millions of users recieving and sending each-other tips or payments, GigaWallet aims to be adaptable to each scenario. To achieve this aim we have some simple abstractions for managing payment:

Accounts

An Account manages a Dogecoin HD wallet, which is used to sign transactions for outgoing payments, and create child-addresses for each Invoice issued.

Accounts are created using the POST /account Admin API, and require a foreignID from your system which will be used to address the account on further API calls.

Accounts have many Invoices which represent requests for payment, as well as a Balance which tracks current available Dogecoin and current pending incoming and outgoing transactions.

How you map Accounts to your system depends on your objective, you may have an account per user in the case of a Social Media platform, or if you are an entity with a number of clients you could choose to manage each with their own pay-to account.

You can read more about Accounts here.

Invoices

Accounts are used to issue Invoices, which are a collection of Items with quantities and values. Items represent a line on the invoice and come in a number of types: item, tax, fee, shipping, discount, donation, etc.

An invoice is created using the POST /account/:foreignID/invoice Admin API and once created cannot be modified, GigaWallet is not a shopping-cart system and if you want users to be able to add/remove items that should happen on your side before an Invoice is issued.

Invoices provide payment URLs, QRCodes and DogeConnect JSON Payloads via the Public API which can be used by your front-end to provide convenience payment options for your users.

You can read more about Invoices here.

Dogecoin Connect

Public API

Admin API

Installation

Pre-requisites

GigaWallet is intentionally easy to compile and run, weather you are looking to build from source or via containers, we've got you covered.

Golang compiler

To build from source you will need the Golang compiler installed. Head on over to go.dev and grab a copy for your local environment.

Dogecoin Core Node

GigaWallet currently depends on a co-located instance of the Dogecoin Core Node project, we recommend building this without the wallet / QT features, and with the RPC APIs.

⚠️ Important: Gigawallet trusts the Core Node to provide accurate blockchain data; for this reason is critically important to use a Core Node that you fully trust. It's safest to host the Core Node yourself.

If you would like to build this yourself or download binaries you can grab these at Github.com/dogecoin/dogecoin,

alternatively if you're happy with containers or packages try the NixOS or Docker deployment methods.

⚠️ Note: Running a full core node requires a significant amount of disk to contain the entire Dogecoin blockchain (140Gb as at March 2024), as well as a moderate amound of bandwidth.

Building from source

Install some dependencies required to build Gigawallet:

  • GCC compiler toolchain (for cgo i.e. Go-to-C linking; only GCC is supported!)
  • zeroMQ version 4 – docs wiki
  • SQLite 3 – docs
sudo apt-get update
sudo apt-get install libzmq3-dev sqlite3 libsqlite3-dev build-essential pkg-config

On Windows: you can use WSL to install these tools, and build Gigawallet from inside the WSL environment (you can access windows drives via /mnt/c etc.) Alternatively there is MSYS2 which provides a GCC build environment without using WSL.

On Mac: you can use Homebrew: brew install zmq pkg-config – note that sqlite3 is pre-installed on modern macs. You can brew install git if necessary.

Building Gigawallet

Check out the project from Github and run make

> git clone git@github.com:dogecoinfoundation/gigawallet.git
...

> cd gigawallet
> make

This will create a gigawallet binary in /build/.

gigawallet has several subcommands:

  • ./gigawallet server starts the server running.
  • ./gigawallet printconf will dump out the config structure and exit.
  • ./gigawallet setsyncheight <height> will rewind the entire db and begin re-indexing from core, you probably don't need this.. probably.

⚠️ Note: Developer Shortcut If you are developing in the repository you can simply run make dev which will stand-up the server using the devconf.toml file. VS Code debugger also works.

Configuration

Config file location

By default the gigawallet command will look for a config.toml file in one of:

. 
/etc/gigawallet/ 
$HOME/.gigawallet/

The name of the config file can be changed by providing the GIGA_ENV environment variable. This allows you to operate several different config files and switch between them, for instance if you have:

/etc/gigawallet/production.toml
/etc/gigawallet/staging.toml

You could switch between them with GIGA_ENV=production gigawallet <subcommands>.

Eaxample config

There is an exmaple config file which is kept current with the software in the repo https://raw.githubusercontent.com/dogecoinfoundation/gigawallet/main/devconf.toml which you can use as a starting point.

Configure API ports

Gigawallet exposes two REST APIs:

  • Admin API which provides sensitive, internal functionality which is called from your own backend services, and must be protected behind a firewall.

  • Public API which provides web-facing routes for your front-end calls, for fetching Invoice data, QR codes for payments, and the Doge Connect protocol endpoints. We recommend this sit behind your load-balancer/proxy and be routed to as required for your needs.

pubapirooturl is used internally when generating Doge Connect payloads to allow clients to submit payments back to Gigawallet for processing.

[WebAPI]
  adminbind = "localhost"
  adminport = "8081"
  pubbind = "localhost"
  pubport = "8082"
  pubapirooturl = "https://example.com/gigawallet"

Configure the data store

Gigawallet currently operates using SQLite or PostgreSQL databases. We recommend using sqlite for development / local testing, and PostgreSQL for production. Also note that you can easily extend Gigawallet for different databases, see Extending.

Running with sqlite (default)

[Store]
  DBFile = "gigawallet.db"

Running with PostgreSQL

[Store]
  DBFile = "postgres://username:password@localhost/gigawallet?sslmode=disable"

Currently Gigawallet PostgreSQL requires full permissions to create tables / indexes which is an unfortunate side-effect of our sqlite-first development, this will be changed in the future, however for now here is a quick-start for setting up a new DB:

-- create a database, you can call it whatever you like.
CREATE DATABASE gigawallet;

-- create a user, pick a better password than this!
CREATE USER gigawallet WITH PASSWORD 'up-up-down-down-left-right-left-right-b-a-start';

-- set the database owner and grant permissions
ALTER DATABASE gigawallet OWNER TO gigawallet;
GRANT ALL ON DATABASE gigawallet TO gigawallet;

As mentioned above, Gigawallet will create all tables it needs on first run.

Configuring Core access

As mentioned above, Gigawallet is currently designed to co-locate with a Core instance for communicating with the Dogecoin L1 network.

You can create as many [dogecoind.nnnnn] sections as you like to represent access to various Core instances you may have, which gets used is determined by the gigawallet.network value.


[gigawallet]
  network = "mainnet"  # which dogecoind to connect to

[dogecoind.testnet]
  host    = "127.0.0.1"
  zmqport = 28332
  rpcport = 44555
  rpcpass = "gigawallet"
  rpcuser = "gigawallet"

[dogecoind.mainnet]
  host    = "127.0.0.1"
  zmqport = 28332
  rpchost = "127.0.0.1"
  rpcport = 22555
  rpcpass = "gigawallet"
  rpcuser = "gigawallet"

Configuring Loggers

Gigawallet can create as many loggers as you like, these log events that cross the [internal event-bus]. Events have a type which is one of:

  • SYS - System messages & errors.
  • ACC - Account events.
  • INV - Invoice events.
  • NET - Network (L1) events.
  • ALL - Synthetic type which catches all of the above.

Loggers are specified as a list of types and a path:

[loggers.events]
  path = "./events.log"
  types = ["ALL"]

[loggers.system]  
  path = "./system.log"
  types = ["SYS"]
  

Configuring HTTP Callbacks

Callbacks or 'webhooks' are URLs which you can configure to recieve HTTP POST requests containing JSON-encoded event bodies. This can be used by your system to respond to events such as invoice paid etc.

To configure callbacks, provide a path and a type of event you'd like (see Loggers for a list)

[callbacks.example1]
  path = "https://example.com/MyInvoiceEvents"
  types = ["INV"]

Configuring MQTT topics

If http callbacks are not your thing, you can send events to an MQTT compatible message service. Firstly use the [mqtt] block to configure the server you'd like to connect to, then set up one or more [mqtt.queues.*] blocks with a topicfilter and types of events to send.

[mqtt]
  address = "test.mosquitto.org:1884"
  username = "rw"
  password = "readwrite"
  clientid = "gigawallet"

[mqtt.queues.accounts]
  topicfilter = "account"
  Types = ["ACC"]

Running with NixOS

TODO

Running with Docker

TODO

Working with Accounts

Gigawallet is designed as a backend component that sits within your infrastructure, and as such is not supposed to be your system's user-database. It is designed with a fairly generic Account model which can be used as you see fit to match your business needs.

Each Account within Gigawallet represents a Dogecoin HD Wallet, which is used to derive child-addresses per Invoice. Accounts can list invoices, refund payments and have a Balance of their own.

Accounts are created with a Foreign ID which is provided by you and links the account to your system. Most Admin APIs use this Foreign ID to reference internal accounts so that you can easily integrate Gigawallet with your own systems.

Different ways to use Accounts with your system

Scenario 1 - Wholesale Store

You are a wholesale business selling dog-collars, dog-leads and accessories to pet stores. You have a customers database with a Customer ID number for each pet store. You create a Gigawallet Account per customer using your Customer ID as the Foreign ID.

You can:

  • Issue invoices to your customers, including shipping fees and taxes.
  • List invoices per customer.
  • Manage refunds with a 'wallet' per customer to ensure funds are accessible.
  • Check total balances received and pay those out to your central wallet when ready.

Scenario 2 - Online Dogecoin Payments SaaS

You are a payment provider like PayPal, Square, etc. And are looking for a method to manage Dogecoin payments. You have a users database with a snowflake ID per user. You create a Gigawallet Account per user using your snowflake ID as the Foreign ID.

You can:

  • Issue invoices on behalf of your users.
  • Automatically pay-out to your user's cold wallet based on various thresholds.
  • Provide a realtime balance of user's funds.
  • Provide reports on payments in and out over time.

Scenario 3 - Traditional Crypto Exchange

You are a traditional Crypto Exchange managing trades on behalf of your users. Gigawallet is configured with an account per user, consistent with your existing user databases.

You can:

  • Recieve payment in Dogecoin from your users into their Dogecoin wallet for trading.
  • Pay Dogecoin to your users wallet once trading is complete.
  • Provide balance and reports on payments to and from their wallets.
  • Configure auto-payouts to your users cold-wallet so they don't leave their Dogecoin on exchanges.

Scenario 4 - Global Scale platform ie: X.com, Twitch TV, EBay, etc.

You are a large scale unicorn with hundreds of millions of users. Your infrastructure teams can deploy Gigawallet in multiple configurations on your kubernetes clusters with appropriate auto-scaling and user sharding (in development). Gigawallet integrates directly into your existing stack with simple REST calls.

You can:

  • Give each user the ability to recieve tips, accept and make payments, pay for products and subscriptions.
  • Query balances and issue payouts to users personal wallets.
  • Integrate Gigawallet directly into your messaging system (via MQTT) to trigger events when payments are confirmed.
  • Help Dogecoin gain real utility as a global currency for all humanity.

Account Administration APIs

POST /account/:foreignID

Create or update an Account

:foreignID is a gobal, (or shard)-unique identifier from your system which you will use to address this account in subsequent requests.

REQUEST BODY:

Expected POST Body, an empty {} is fine to touch an account into existence.

{
  "payout_address" : "<P2PKH Dogecoin Address>",  // optional for auto-payout
  "payout_threshold" : "<decimal amount of dogecoin before auto-payout>" //optional 
  "payout_frequency" : "<duration in seconds for time-based auto-payouts>" //optional 
}

RESPONSE BODY:

Example response from POST {} /account/123456789

{
    "foreign_id": "12345789",
    "id": "DRQu6WR6bpU9N4rm87PvpWZLQSqmGgphFD",
    "payout_address": "",
    "payout_frequency": "",
    "payout_threshold": "0"
}

Your account is now created with an HD wallet managed by Gigawallet.

GET /account/:foreignID

Get an Account

RESPONSE BODY:

Example response from GET /account/123456789

{
    "foreign_id": "12345789",
    "id": "DRQu6WR6bpU9N4rm87PvpWZLQSqmGgphFD",
    "payout_address": "",
    "payout_frequency": "",
    "payout_threshold": "0"
}

GET /account/:foreignID/balance

Get an Account's AccountBalance

{
    "CurrentBalance": "1000",       // Current balance available for spending 
    "IncomingBalance": "24.89774",  // Incoming payments which have not met the confirmation threshold
    "OutgoingBalance": "0"          // Outgoing payments which have not met the confirmation threshold
}

POST /account/:foreignID/pay

Send a payment from this account to an Address

REQUEST BODY:

{ "amount": "420.69, "to": "DPeTgZm7LabnmFTJkAPfADkwiKreEMmzio" } 

Account Events

Events are available either via http callbacks or MQTT messages.

TODO

ACC_CREATED "CREATED"

ACC_UPDATED "UPDATED"

ACC_PAYMENT "PAYMENT"

ACC_CHAIN_ACTIVITY "CHAIN_ACTIVITY"

ACC_BALANCE_CHANGE "BALANCE_CHANGE"

Working with Invoices

Once you have Accounts established it's time to start issuing Invoices. Invoices are simply a list of items, services, taxes, fees, discounts etc. which a seller is offering for payment in Dogecoin.

📚 Wikipedia: An invoice, bill or tab is a commercial document issued by a seller to a buyer relating to a sale transaction and indicating the products, quantities, and agreed-upon prices for products or services the seller had provided the buyer.

As mentioned previously Gigawallet is not your general-purpose user database, just so it is not your general purpose shopping-cart either. For this reason Invoices are specifically designed to encourage you to have finalised all purchase decisions before issuing an Invoice as the final step when your user wants to pay in Dogecoin. Once created an invoice cannot be directly updated (this is a design decision!) Gigawallet is a payment system for Dogecoin.

Parts of an Invoice

An invoice is created via the POST /account/:foreignID/invoice endpoint and consists of a list of items along with metadata about the status of the payment. Here is an example invoice:

{
  "id": "DNBVSoHLhX4gQiGLdZJhXMe7XZWuD7orVo",
  "items": [
    {
      "type": "item",
      "name": "A segment of Toblerone",
      "sku": "TOB001",
      "description": "You can share my Toblerone, for 1 Dogecoin!",
      "value": "1",
      "quantity": 1,
      "image_link": ""
    }
  ],
  "created": "2023-08-17T15:40:13.935244+10:00",
  "total": "1",
  "pay_to_address": "DNBVSoHLhX4gQiGLdZJhXMe7XZWuD7orVo",
  "part_payment_detected": false,
  "total_payment_detected": false,
  "total_payment_confirmed": false,
  "payment_unconfirmed": false,
  "estimate_seconds_to_confirm": 0
}

id

This is a unique ID, it also happens to be the public child address generated from the account HD wallet for this invoice. You'll notice it's identical to pay_to_address for that reason, you can use this to reference the invoice in future API calls or as a unique identifier for the invoice in your own system.

items

Items is an array of line items that get passed in when the invoice is created, Items have a value which is a decimal amount of Dogecoin, as a string, per item. This is multiplied by quantity and summed across all items to derrive the invoice total.

Items also have a type which must be one of:

  • item
  • tax
  • fee
  • shipping
  • discount

These types are primarily used to distinguish line-items in UI, so that taxes, shipping and fees can be grouped separately. We do validate that all item values are a positve amount, except for items of type discount which must be a negative amount.

total

This is the total calculated amount owing for the invoice to be considered paid, and is calculated as the sum of all item values * quantity. This is a decimal value as a string.

pay_to_address

This is the dogecoin address for recieving invoice payment.

part_payment_detected

This is a boolean flag that will be set when GigaWallet first detects any kind of payment in a block. This may or may not be the total amount owing.

total_payment_detected

This is a boolean flag that will be set when GigaWallet first detects a payment in a block that would complete the total amount owing.

total_payment_confirmed

This is a boolean flag that will be set when GigaWallet detects that required_confirmations have been met on the network, this is the best means of determining payment has been made.

payment_unconfirmed

This boolean will only be set in the event that required_confirmations has been met and confirmed, however the blockchain has forked and eliminated your payment. This should only occur in the event that you are using a very low required_confirmations count.

⚠️ Note: What should you do in this event? Did I just lose my Dogecoin?

GigaWallet cannot hide you from the reality of the blockchain and the potential for soft-forks, in day to day running we see these tip-reorgs happening semi regularly and removing 1 or at most 2 blocks of confirmation. In the event that a tip-reorg happens and that decrements the required number of confirmations or even eliminates your payment, it is highly likely that the transaction will be included in a new block shortly. GigaWallet will then re-issue and re-set the appropriate events / flags on the new tip.

It is possible that the payer has intentionally issued a double-spend transaction hoping to fake payment, we recommend that you set a required_confirmations value commensurate with the amount of Dogecoin in your invoice and the appropriate level of risk. If you are selling someone a Coffee for 30 Dogecoin perhaps a 1 block confirmation is fine, if you are selling a million dollar house, there is no reason not to wait for 20-30 confirmations, the ink will still be wet on the page anyway.

estimate_seconds_to_confirm

Once an intial payment has been seen, this value will be an estimate of the remaining seconds before confirmation based on the required_confirmations set for this Invoice. This is useful for anyone using a poll-method to query payment as you can roughly predict the wait-time. If no payment has been seen or the invoice is already paid this value will be 0.

Admin API

POST /account/:foreignID/invoice

_Create an Invoice

:foreignID is the unique identifier from your system which you used to create an account.

REQUEST BODY:

Expected POST Body:

{
  "items": [
    {
      "name": "Dogecoin Sticker",
      "value": "100.00",
      "quantity": 1,
      "type": "item"
    }
  ],
  "required_confirmations": 3
}

RESPONSE BODY:

{
  "id": "DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH",
  "items": [
    {
      "type": "item",
      "name": "Dogecoin Sticker",
      "sku": "",
      "description": "",
      "value": "100",
      "quantity": 1,
      "image_link": ""
    }
  ],
  "created": "2023-08-30T16:49:51.705419+10:00",
  "total": "100",
  "pay_to_address": "DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH",
  "part_payment_detected": false,
  "total_payment_detected": false,
  "total_payment_confirmed": false,
  "payment_unconfirmed": false,
  "estimate_seconds_to_confirm": 0
}

GET /account/:foreignID/invoice/:invoiceID

Get an Invoice for a specific account

:foreignID is the unique identifier from your system which you used to create an account. :invoiceID is the unique identifier for an invoice, ie: DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH.

RESPONSE BODY:

{
  "id": "DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH",
  "items": [
    {
      "type": "item",
      "name": "Dogecoin Sticker",
      "sku": "",
      "description": "",
      "value": "100",
      "quantity": 1,
      "image_link": ""
    }
  ],
  "created": "2023-08-30T16:49:51.705419+10:00",
  "total": "100",
  "pay_to_address": "DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH",
  "part_payment_detected": false,
  "total_payment_detected": false,
  "total_payment_confirmed": false,
  "payment_unconfirmed": false,
  "estimate_seconds_to_confirm": 0
}

GET /account/:foreignID/invoices?limit=100&cursor=0

Enumerate an Invoice for a specific account.

:foreignID is the unique identifier from your system which you used to create an account. limit is the maximum number of records to return. cursor starts at 0, and should be set to the cursor value returned by a previous call.

Those familiar with popular cursor-based APIs such as AWS etc should understand this pattern, it allows for machine-to-machine fetching of all invoices and should not be confused with an offset/limit style API.

The response contains two elements, items which is an array of invoices, and cursor which should be passed to the next invocation. A cursor of 0 indicates there are no further records.

RESPONSE BODY:

{
"items": [
      {
        "id": "DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH",
        "items": [
          {
            "type": "item",
            "name": "Dogecoin Sticker",
            "sku": "",
            "description": "",
            "value": "100",
            "quantity": 1,
            "image_link": ""
          }
        ],
        "created": "2023-08-30T16:49:51.705419+10:00",
        "total": "100",
        "pay_to_address": "DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH",
        "part_payment_detected": false,
        "total_payment_detected": false,
        "total_payment_confirmed": false,
        "payment_unconfirmed": false,
        "estimate_seconds_to_confirm": 0
      }
  ],
  "cursor": 0
}

Public API

The public invoice APIs are available on a different port which is designed to be exposed to the internet via your proxy or as part of your own API gateway. These APIs can be called by web or mobile clients, with the aim of providing payment info to the payer. We imagine you will use these apis to show the payer a list of items they are purchasing, and to provide details / address / QRcodes etc to facilitate payment.

GET /invoice/:invoiceID

Get an Invoice

:invoiceID is the unique identifier for an invoice, ie: DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH.

RESPONSE BODY:

{
  "id": "DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH",
  "items": [
    {
      "type": "item",
      "name": "Dogecoin Sticker",
      "sku": "",
      "description": "",
      "value": "100",
      "quantity": 1,
      "image_link": ""
    }
  ],
  "created": "2023-08-30T16:49:51.705419+10:00",
  "total": "100",
  "pay_to_address": "DMcUQWwMdpdXqiYNiYgCzrM5Wn85dYerQH",
  "part_payment_detected": false,
  "total_payment_detected": false,
  "total_payment_confirmed": false,
  "payment_unconfirmed": false,
  "estimate_seconds_to_confirm": 0
}

GET /invoice/:invoiceID/qr.png

This endpoint does not return JSON, it returns a PNG image of a QR code containing a dogecoin address in the format:

dogecoin:<address>?amount=<amount>&ctx=<dogeconnect url>

The address is the pay_to_address in the invoice. The amount is the total dogecoin in the invoice. The ctx is a URL that points to a dogecoin connect payload.

qr code

This can be directly placed on your payment page and if scanned will load the user's Dogecoin wallet to make a payment for the full amount of the invoice. This could be used in a web interface, or even emailed or mailed with an invoice allowing immediate payment by the recipient.

GET /invoice/:invoiceID/connect

This endpoint returns a dogecoin connect payload which is defined as a new protocol to facilitate payment from a self-custodial wallet without needing access to a relay.

The concept is that a Dogecoin wallet which understands the dogecoin connect protocol can present in it's own UI, an invoice complete with items being purchased and have the user generate a transaction which can be issued back to GigaWallet directly where it will be validated and sent to the mempool.

This will allow GigaWallet to support zero-confirmation payments, aka instant payments which are required for fast-turn-around services such as vending machines, coffee shops, etc.

{
  "version": "0.1",
  "service_name": "Example Dogecoin Store",
  "service_icon_url": "https://example.com/icon.png",
  "service_domain": "example.com",
  "service_key_hash": "...",
  "payload": "eyJ0eXBlIjoiaW52b2ljZSIsInJlcXVlc3...",
  "hash": "..."
}

The JSON body contains a payload which is signed by the issuing store key which can be stored on the client once recognised for the first time. This protocol is still under development and support is incomplete, watch this space!

Doge Connect - Payment Protocol

Paying Out

Webhooks

MQTT

Extending

component diagram of GigaWallet