Algorand Funding Protocol

The Immersve Flexi Algorand funding protocol allows client applications to fund Immersve cards via simple native Algorand Asset transfers. Depositors can withdraw funds at any time with signed withdrawal approvals. Deposits are scoped to a single Immersve partner application. Depositor funds can only be settled to Immersve's approved settlement address.

Smart Contract

The Flexi Algorand protocol has a Master contract and many partner Partner Channel and Card Fund contracts. Card Fund contracts hold deposits for a cardholder. Partner Channel contracts scope the Card Fund contracts to an Immersve partner application. Partner Channel and Card Fund contracts are managed by the Master Contract.

Source

https://github.com/immersve/funding-contract-algorand

Deployed Contract Addresses

The Flexi Algorand protocol is designed to work on the Algorand networks. The deployed contract application ids are listed below.

NetworkAddress
Algorand2174001591
Algorand Testnet702773232

Smart Contract Overview

The Master contract is the main entry point and is a factory for the Partner Channel and Card Fund contracts. Card Fund contracts are the target for depositor native asset transfers that are scoped to an integrated partner application. The Master contract is also used by Immersve for performing settlements and refunds.

The Partner Channel contract is used to identify the partner to which a Card Fund contract belongs. The Partner Channel is provisioned by the Immersve card issuing partner.

The Card Fund contract holds assets for funding a cardholders card. Deposits are made via native token transfers. The Card Fund is provisioned by the cardholder. A Card Fund contract is uniquely identified by the address of the owner (the cardholder's primary algorand address) and the address of the related partner contract.

flexi-algorand-overview
Algorand smart contract component diagram.

Upon receiving a card payment request, a Card Fund contract will be debited by Immersve. The debited funds move to the Master Contract where they wait to be cleared for settlement.

flexi-algorand-overview
Algorand funds flow diagram.

Protocol Mechanics

Deposits

Depositors can send native asset transfers directly to the Card Funds address. The depositor needs to have an Immersve Funding Source registered for each asset supported by their Card Fund. The Funding Source is an off-chain representation of available balance that is connected with the Immersve cardholder account and used to authorize payments.

After an asset transfer transaction is observed by Immersve, the connected Funding Source will be credited with the deposited amount. When a Funding Source is created, any deposits made before the creation of the Funding Source associated with the depositing address will be credited immediately.

The Get Spending Prerequisites endpoint can be used to reliably obtain the Algorand transaction parameters for depositing into a Funding Source. See Card Funding for more details.

Withdrawals

Withdrawals are approved by the Immersve platform and executed by calling the cardFundExecuteApprovedWithdrawal() function on the Card Funds contract. The signed withdrawal approval, and all other parameters required for submitting the withdrawal transaction to the Algorand chain, are obtained by calling the Create Withdrawal Intent API endpoint. See Card Funding for more details.

Partner Setup

Creating a Partner Channel Instance

A Partner Channel instance needs to be created for an Immersve partner to start supporting funding on the Algorand network. It only needs to be created once for all depositors. The address of the created Partner Channel will need to be supplied when Creating a Funding Channel.

Creating a Partner Channel instance requires two steps: deployment init and complete. To initialize the creation of the Partner Channel instance, invoke the partnerChannelDeployInit() function on the Master contract. The init function will return the address of the Partner Channel. Once a Partner Channel instance is initialized, the deployment can be completed calling the partnerChannelDeployComplete() function.

After deployment is completed, the address of the deployed Partner Channel instance can also be discovered from the Algorand transaction logs. In a block explorer, find the PartnerChannelCreated event within the logs for the transaction that created the Partner Channel instance.

Use the created partner channel address as the contractAddress when calling the Create Funding Channel endpoint. A Funding Channel is required for each supported asset.

Creating a Card Funds Instance

A Card Fund instance needs to be created for each partner Cardholder account. Use the created Card Fund address as the fundingAddress when calling the Create Funding Source endpoint. The Algorand address that creates the Card Fund address is the owner. There can only be a single Card Fund contract instance per owner address per Partner Channel. Only the owner address can receive withdrawals from a Card Fund address.

Creating a Card Fund instance requires two steps: deployment init and complete. To initialize the creation of the Card Fund instance, invoke the cardFundDeployInit() function on the Master contract. Find the Master contract address for your target chain from "Contract Addresses" above. This function will return the address of the Card Fund to be used in the next step cardFundDeployComplete().

Once a Card Fund instance is initialized, the deployment can be completed calling the cardFundDeployComplete() function.

The address of a deployed Card Fund instance can be discovered by calling getCardFundByPartner(). The address can also be found in the Algorand transaction event logs. In a block explorer, find the CardFundCreated event within the logs for the transaction that created the Card Fund instance. This event will be emitted by the cardFundDeployComplete() function.

Card Fund can support multiple Assets at the same time. They just need to be enabled via cardFundEnableAsset(). Only assets already supported by Immersve can be opted-in. For each opted-in asset, a separate Funding Source needs to be registered.

Functions

partnerChannelDeployInit(mbr, partnerChannelName)

Initializes the deployment of a new Partner Channel contract. The caller must be opted-in to the app to complete this function call.
Returns
Address — The Partner Channel address that can be used to complete the deployment when calling partnerChannelDeployComplete().
Params
mbr: PayTxn — A payment transaction to supply the minimum balance requirement for the partner channel account. The amount must be 0.1 Algo.
partnerChannelName: string — The name of the deployed contract. This is used only for debugging purposes and must be globally unique. Using your app name, and "liveness" in the name are recommended, for example: "Acme Wallet USDC Live".

partnerChannelDeployComplete(mbr, partnerChannelAddr)

Completes the setup of a new Partner Channel contract.
Params
mbr: PayTxn — A payment transaction to supply the minimum balance requirement for storing the partner state on the Master contract. The amount can be fetched from getPartnerChannelBoxMbr().
partnerChannelAddr: Address — The address of the partnerChannel created by partnerChannelDeployInit().

cardFundDeployInit(mbr, partnerChannel, asset, reference)

Initializes the deployment of a new Card Fund contract. The caller must be opted-in to the app to complete this function call.
Returns
Address — The Card Fund address that can be used to complete the deployment when calling cardFundDeployComplete().
Params
mbr: PayTxn — A payment transaction to supply the minimum balance requirement for creating the Card Fund address. The amount must be 0.2 Algo
partnerChannel: Address — The Partner Channel address to which the Card Fund is bound. Deposits to the created Card Fund will only be spendable by an Immersve cardholder who is connected with this partner.
asset: AssetID — The asset id to initially opt-in. See Supported Tokens for available assets to opt-in.
reference: string — The external reference string to be stored on the Card Fund contract data. This could be used to back link a card fund with a cardholder account or any other user defined data

cardFundDeployComplete(mbr, cardFundAddr)

Completes the setup of a new Card Fund contract.
Params
mbr: PayTxn — A payment transaction to supply the minimum balance requirement for creating the Card Fund address. The amount for the MBR transaction can be fetched from getCardFundBoxMbr().
cardFundAddr: Address — The address of the Card Fund created by cardFundDeployInit().

cardFundEnableAsset(mbr, cardFund, asset)

Opt-in a Card Fund to an additional asset.
Params
mbr: PayTxn — A payment transaction to supply the minimum balance requirement for the asset opt-in. The amount for the MBR transaction can be fetched from getCardFundAssetMbr().
cardFund: Address — The Card Fund address that is opting in to the asset.
asset: AssetID — The asset id to opt-in. See Supported Tokens for available assets to opt-in.

getCardFundByPartner(channel, owner)

Find an existing Card Fund address for a Partner Channel and owner combination.
Params
channel: Address — The address of the Partner Channel contract.
owner: Address — The address of the Card Fund owner.

cardFundExecuteApprovedWithdrawal(cardFund, asset, amount, expiry, nonce, signature)

Execute a withdrawal initiated by calling the Create Withdrawal Intent endpoint.
Params
cardFund: Address — The address of the card being withdrawn from.
asset: AssetID — The id of the asset being withdrawn.
amount: uint64 — The amount of the withdrawal.
expiry: uint64 — The expiry of the withdrawal signature.
nonce: uint64 — The next withdrawal nonce.
signature: bytes64 — The withdrawal signature issued by Immersve.