Write to Blockchain
The blockchain can be thought of as a general-purpose, publically viewable and verified, database. To write to a blockchain, similar to with a typical database, you must make a transaction. Typically, creating a blockchain transaction is rather complex, but Embedded Wallet handles that complexity for you and exposes 5 types ofTransactions.
Sending a transaction is an asynchronous Task. You can use await when calling SequenceWallet.SendTransaction if you wish to obtain the TransactionReturn object directly. Or, you can take the recommended approach which is to setup handler functions for the SequenceWallet.OnSendTransactionComplete and SequenceWallet.OnSendTransactionFailed events and call the SequenceWallet.SendTransaction method from anywhere (without await). For example:
RawTransaction
The most basic form of aTransaction, a raw transaction, is very useful to send ETH or the gas currency of the network you are interacting with to an Address.
For example, to send one MATIC to 0x9766bf76b2E3e7BCB8c61410A3fC873f1e89b43f you can use this snippet:
1000000000000000000 (1 * 10^18) as ETH, MATIC, and most gas currencies have a “decimals” value of 18. DecimalNormalizer.Normalize (above) is a basic helper function that will return input value * 10^decimals and optionally accepts a “decimals” value as a second parameter (defaulting to 18 when not provided).
Additionally, you can include data with a raw transaction in hexadecimal format as a string. For more on this, please see the advanced section of this documentation.
sendERC20
An ERC20 token is the fungible token standard. You can easily deploy an ERC20 contract and mint tokens using our Builder. Learn how in our Builder documentation. To send an ERC20 token transaction, you can use this code snippet:DecimalNormalizer.Normalize to convert the amount from human readable format to EVM format. Please make sure to include the optional “decimals” int parameter if your ERC20 token has a “decimals” value that is not 18. If you’re not sure how many “decimals” your ERC20 has, this can be easily read on the Builder using the “decimals” method under “Read Contract”.
Complex ERC20 Interactions
For interactions with ERC20 tokens outside of basic transfers, you’ll want to use ourSequenceEthereum library provided with the SDK. We’ve created ERC20 smart contract wrapper functions for your convenience that allow you to create and send RawTransactions with Embedded Wallets.
First, you’ll need to create an ERC20 object by providing a contract address and optionally, an ABI string, if you are using a custom variation of the ERC20 standard (not recommended).
CallContractFunction, e.g. Mint, can be used when creating a RawTransaction with Embedded Wallets. For example:
sendERC721
An ERC721 token is the non-fungible standard, you’ve probably heard of them as NFTs. You can easily deploy an ERC721 contract and mint tokens using our Builder. Learn how in our Builder documentation. To send an ERC721 token transaction, you can use this code snippet:Complex ERC721 Interactions
For interactions with ERC721 tokens outside of basic transfers, you’ll want to use ourSequenceEthereum library provided with the SDK. We’ve created ERC21 smart contract wrapper functions for your convenience that allow you to create and send RawTransactions with Embedded Wallets.
First, you’ll need to create an ERC721 object by providing a contract address and optionally, an ABI string, if you are using a custom variation of the ERC721 standard (not recommended).
CallContractFunction, e.g. SafeMint, can be used when creating a RawTransaction with Embedded Wallets. For example:
sendERC1155
An ERC1155 token is the multi token standard, often referred to as SFTs (semi-fungible tokens). As co-creators of the ERC1155 standard we are firm believers in its unparalleled usefulness for games. You can easily deploy an ERC1155 contract and mint tokens using our Builder. Learn how in our Builder documentation. To send an ERC1155 token transaction, you can use this code snippet:SendERC1155Values objects in the transaction
Complex ERC1155 Interactions
For interactions with ERC1155 tokens outside of basic transfers, you’ll want to use ourSequenceEthereum library provided with the SDK. We’ve created ERC1155 smart contract wrapper functions for your convenience that allow you to create and send RawTransactions with Embedded Wallets.
First, you’ll need to create an ERC1155 object by providing a contract address and optionally, an ABI string, if you are using a custom variation of the ERC1155 standard (not recommended).
CallContractFunction, e.g. Mint, can be used when creating a RawTransaction with Embedded Wallets. For example:
SequenceContractCall
When calling a smart contract on an EVM-based network, the client goes through a complex process known as “ABI encoding” where the function signature you want to call as well as the parameters you’re providing are encoded into a binary format. This process is complicated and error-prone so we’ve abstracted it all away so that you don’t have to deal with it. But, if you’re curious to learn how it works, please see this document. A SequenceContractCall transaction allows you to call any method on an arbitrary smart contract, allowing us to handle the complicated ABI encoding process server-side. To send a SequenceContractCall transaction, you can use this code snippet:payable keyword in the smart contract definition. If you are calling a payable method, it is recommended to use DecimalNormalizer.Normalize to convert the amount from human readable format to EVM format. Note that the user will need to have the required funds in their wallet in order to pay the value specified to a payable function. This parameter can be omitted to default to “0”.
FunctionABIAsString: The function you plan on interacting with. We’d recommend copy-pasting the function signature (with parameters) from the contract source code on Etherscan (or the appropriate block explorer for your network) and removing the whitespace and variable names.
ParametersAsObjectArray: The parameters you want to provide to the method you wish to call. No need to provide the parameter names, just their values in the order they appear in the ABI. Provide parameters in string format when in doubt.
Putting this together, an example of using SequenceContractCall to call the “mint” function on an ERC20 would look like this:
Batch Transactions
Using the magic of the Sequence Smart Contract wallet, our SDK allows you to seemlessly batch transactions together. Batching transactions together is extremely beneficial as it provides material gas savings and allows you to create complex transactions, that either all pass or all fail, without deploying custom smart contracts for each bespoke use case, opening a whole new realm of design possibilities! Sending a batch transaction is easy! Simply include multiple transactions, of any type, in your transaction array when making theSendTransaction request.
For example - sending a transaction of each type in a batch:
FeeOptions
By default, the SDK will automatically sponsor all Embedded Wallet transactions using your Builder API credits. However, in some niche use cases, you may find that you would prefer not to sponsor your users’ transactions. This requires that your users are more experienced Web3 users and have tokens/gas currency in their wallet that can be used to pay gas fees. In addition to the gas currency for the selected network, gas fees can also be paid using select ERC20 and ERC1155 tokens.Transaction sponsoring is only available for Developer tier and above. For more information on gas sponsoring, please see this document. For more information on upgrading your project billing tier, please see this guide.
FeeOptionsResponse contains a FeeQuote (string) that locks in the price for each FeeOptionReturn in the FeeOptions array that is returned for a limited time; you’ll need this in a moment when submitting your transactions. For your convenience, the SDK will automatically query the user’s wallet to see which of the FeeOptions the user can afford using the Indexer.
From here, you can display a UI to the user to allow them to select how they would like to pay the fee for their transactions.
Once the user has selected how they’d like to pay their fee, you may submit the transactions, including the selected FeeOption and the FeeQuote string.
Demo Scene that can be imported via Package Manager > Samples, you can see a barebones example usage of FeeOptions. Here, we do not provide a UI and instead opt to use the first available FeeOption in the user’s wallet. We do not recommend using this approach in a real game, but it serves as a useful example for your own integration. See our sample code below:
Transaction Queuers
When working with the blockchain, it is important to batch transactions in order to minimize gas fees. In order to make this easier to do, we’ve provided a flexibleTransactionQueuer with the SDK that can be configured or extended to suit your needs. To learn more about Building Transaction Heavy Games in Unity and what to consider, please checkout our guide on the topic.
When you add a TransactionQueuer MonoBehaviour to your scene, there are a few config variables you can set.
AutoSubmitTransactions: defaulting to false, enabling this will configure yourTransactionQueuerto automatically submit any queued transactions wheneverThresholdTimeBetweenTransactionsAddedBeforeSubmittedInSecondshas passed without adding a new transaction to the queueThresholdTimeBetweenTransactionsAddedBeforeSubmittedInSeconds: ifAutoSubmitTransactions == true, automatically submit queued transactions if none is added in the pastThresholdTimeBetweenTransactionsAddedBeforeSubmittedInSecondssecondsMinimumTimeBetweenTransactionSubmissionsInSeconds: a minimum time between submitting queued transactions. With this, you can callTransactionQueuer.SubmitTransactions()as often as you want in your code and transactions will not be submitted unlessMinimumTimeBetweenTransactionSubmissionsInSecondsseconds have passed since the last transaction was pushed. Note: ifTransactionQueuer.SubmitTransactions(overrideWait: true)is called with the optionaloverrideWaitbool flag set to true, theTransactionQueuerwill submit queued transactions regardless of whether or not theMinimumTimeBetweenTransactionSubmissionsInSecondshas passed.
TransactionQueuer exposes a few methods to you:
- Setup: before calling other methods on a
TransactionQueuer, please callSetupon it; this will create and cache the required dependancies - Enqueue: add a transaction to the queue
- SubmitTransactions(bool overrideWait = false, bool waitForReceipt = true): submit the queued transactions if
MinimumTimeBetweenTransactionSubmissionsInSecondshas passed between last transaction submission by theTransactionQueuer. IfoverrideWait = true, submit any queued transactions immediately. IfwaitForReceipt = false, return theTransactionReturnas soon as we get a response from the WaaS API (note: this is only relevant if the WaaS API times out while waiting for a transaction receipt; ifwaitForReceipt = true, we will continually ping a node for a transaction receipt before returning) - ToString(): an override for the typical ToString() function, providing you with better logging support
Don’t forget to call
Setup on your TransactionQueuer!TransactionQueuer class.
SequenceWalletTransactionQueuer
TheSequenceWalletTransactionQueuer allows you to queue up transactions for your user’s Sequence Embedded Wallet.
The SequenceWalletTransactionQueuer expects you to enqueue IQueueableTransactions. This interface is implemented by the QueuedTokenTransaction class. Please feel free to create other classes implementing the IQueueableTransaction interface as needed.
PermissionedMinterTransactionQueuer
ThePermissionedMinterTransactionQueuer is meant to be used for queueing up transactions that are being submitted by your backend server when receiving a signed message from the player’s embedded wallet. It is useful for minting tokens to the player’s wallet when interacting with contracts that require permissions for minting (most token contracts).
The PermissionedMinterTransactionQueuer expects you to enqueue a PermissionedMintTransaction, a basic data transfer object specifying the TokenId and Amount to be minted, and optionally an IMinter. If not provided, the PermissionedMinterTransactionQueuer will default to using the PermissionedMinter class. The PermissionedMinter class will be useful for most use cases; it sends a payload in the following format: