Overview
In this tutorial you’ll learn how to sponsor transactions with Shinami’s Gas Station. For more on the benefits of sponsoring transactions and to see an image of an end-to-end sponsorship flow, see our Gas Station high-level guide The full code for this TypeScript tutorial is available on GitHub. Movement is a fork of Aptos, so developing for both of these chains is very similar. If you’re getting started with Movement, they have some developer docs to help. Orderless transactions: We currently don’t support sponsoring orderless transactions but plan to add this support in the future. If you need this support, please reach out to us atsupport@shinami.com
.
Requests must be from your BE
Our Gas Station does not support CORS, so if you attempt to make requests to it from the FE you’ll get a CORS error. We do this because exposing a Gas Station API key on the FE is a security risk - an attacker could drain the MOVE in your Gas Station fund associated with the key by using it to sponsor transactions. For an overview of ways to integrate frontend signing with backend sponsorship, see our Frontend signing + backend sponsorship tutorial.Understanding errors
Check the error code and message of any errors you get. We outline common errors in our Error Reference - make sure to check out the section specific to Movement Gas Station as well as the “General Error Codes” section at the top that apply to all Shinami services.Usage and Billing FAQ
Make sure to check out the Movement Gas Station product usage FAQ and billing FAQ in our Help Center for answers to common questions.Required setup
Notes:
- This tutorial requires a Shinami account. You can sign up for one here.
- If you have questions not covered by the tutorial you can reach out to us.
1. Create a Shinami Gas Station fund on Testnet
You’ll need a Testnet Gas Station fund in order to sponsor transactions. We have guidance on creating one in the Movement Gas Station page of our Help Center. When you make a Testnet fund we deposit some MOVE in it so you can start testing immediately.2. Clone the github repo and install dependencies
Clone the shinami-examples github repo, cd into theshinami-examples/movement/typescript/backend_examples
directory, and run npm install
to install the dependencies for running the code. If you need to install npm and Node.js, see here . Below, we’ll be using the gas_station.ts
file in the shinami-examples/movement/typescript/backend_examples/src
directory.
3. Create an API access key and copy it into the file.
Create an access key with Testnet Node Service and Gas Station rights You use API access keys to interact with Shinami’s services. For this tutorial, we’ll create one access key that hasGas Station
rights for Testnet transaction sponsorship.
Create an API key in our US East - us1
region as this code uses the US East - us1
service URLs since all services used in this tutorial are deployed there (unlike Tokyo - apac1
). See our Authentication and API Keys guide for info on how to create a key. Make sure to link it to the fund you created in step 1.
Add it to the gas_station.ts file
Once you have your key, use it as the value for the SHINAMI_TESTNET_GAS_STATION_API_KEY
constant. You’ll see that we immediately use it to instantiate a Gas Station client (for sponsoring transactions).
4: Open your Shinami dashboard
Technically not required, but we recommend visiting the “Completed transactions” tab of the Movement Gas Station page of your Shinami dashboard. After running the code examples, take a look at this page. It may take a moment, but you’ll see the digests of transactions you sponsor that are committed to the blockchain appear as in the image below. This tab, and the “In flight transactions” tab (for sponsored transactions that haven’t yet been committed to the Movement blockchain) can be helpful when testing.
Code examples
Overview
Below, we’ll review each of our sample code functions and how to run them. At a high-level, you’ll uncomment just one sample code function - e.g.sponsorTransactionSimple()
in the code block below. Then, save the change, Run tsc
in the shinami-examples/movement/typescript/backend_examples
directory to transpile, and run node build/gas_station.js
to run. This will work as downloaded for the simple transaction examples, but the multi-agent ones require compiling a Move script (explained in the Appendix).
Promise<PendingTransactionResponse>
. If our function was successful, we wait for the transaction to be committed to the blockchain and then print out the hash and status. Example:

Sponsor a simple transaction
Understand the code ThesponsorTransactionSimple
function performs all the steps needed to build, sponsor, sign, and submit a simple transaction:
1
Creates an Account to use as the sender.
2
Builds the transaction (see how it’s done in the Appendix).
3
Sponsors the transaction with a call to Shinami Gas Station. Note that our TypeScript SDK updates the feePayer address upon a successful sponsorship as shown by the
console.log()
statement below.4
Signs the transaction as the sender.
5
Submits the transaction with the sender and feePayer signatures and returns the result.
tsc
in the shinami-examples/movement/typescript/backend_examples
directory to transpile. Then, run node build/gas_station.js
. If successful, you can view the sponsorship on the “Completed transactions” tab of the Movement Gas Station page of your Shinami Dashboard. You can also look up the transaction digest printed to the console in the Movement Explorer (make sure the explorer is set to Testnet).
Sponsor a multi-agent transaction
Understand the code ThesponsorTransactionMultiAgent
function performs all the steps needed to build, sponsor, sign, and submit a multi-agent Move script transaction. Before you run it, you’ll need to generate two funded Accounts that will swap Octa (see how it’s done in the Appendix). The function:
1
Builds the transaction (see how it’s done in the Appendix).
2
Sponsors the transaction with a request to Shinami Gas Station. Note that our TypeScript SDK updates the feePayer address upon a successful sponsorship as shown by the
console.log()
statement below.3
Generates the sender and secondary signer signatures.
4
Submits the transaction with the sender, secondary signer, and feePayer signatures and returns the result.
tsc
in the shinami-examples/movement/typescript/backend_examples
directory to transpile. Then, run node build/gas_station.js
. If successful, you can view the sponsorship on the “Completed transactions” tab of the Movement Gas Station page of your Shinami Dashboard. You can also look up the transaction digest printed to the console in the Movement Explorer (make sure the explorer is set to Testnet).
Sponsor and submit a signed, simple transaction
Understand the code ThesponsorAndSubmitSignedTransactionSimple
function performs all the steps needed to build and sign a simple transaction, and then send it to Gas Station for sponsorship and submission to the Movement blockchain:
1
Creates an Account to use as the sender.
2
Builds the transaction (see how it’s done in the Appendix).
3
Generates the sender’s signature.
4
Makes a request to Gas Station to sponsor and submit the signed transaction, returning the result.
tsc
in the shinami-examples/movement/typescript/backend_examples
directory to transpile. Then, run node build/gas_station.js
. If successful, you can view the sponsorship on the “Completed transactions” tab of the Movement Gas Station page of your Shinami Dashboard. You can also look up the transaction digest printed to the console in the Movement Explorer (make sure the explorer is set to Testnet).
Sponsor and submit a multi-agent transaction
Understand the code ThesponsorAndSubmitSignedTransactionMultiAgent
function performs all the steps needed to build and sign a multi-agent Move script transaction, and then send it to Gas Station for sponsorship and submission to the Movement blockchain. Before you run it, you’ll need to generate two, funded Accounts that will swap Octa if you haven’t already done so (see how it’s done in the Appendix). The function:
1
Builds the transaction (see how it’s done in the Appendix).
2
Generates the sender and secondary signer signatures.
3
Makes a request to Gas Station to sponsor and submit the signed transaction, returning the result.
tsc
in the shinami-examples/movement/typescript/backend_examples
directory to transpile. Then, run node build/gas_station.js
. If successful, you can view the sponsorship on the “Completed transactions” tab of the Movement Gas Station page of your Shinami Dashboard. You can also look up the transaction digest printed to the console in the Movement Explorer (make sure the explorer is set to Testnet).
Check your fund balance and make a deposit
Understand the code ThecheckFundBalanceAndDepositIfNeeded
function does… well, exactly what it says it does 😄. Before you run it, you’ll need to generate a funded Account if you haven’t already done so (see how it’s done in the Appendix). The function:
1
Makes a call to
gas_getFund
to obtain your fund’s balance.2
Checks if the amount that’s available to use is less than the minimum amount you want.
- If true, it:
- creates the transaction to transfer MOVE to your fund address
- obtains the sender’s signature (from the funded Account you made)
- submits the transaction and returns the result.
- Else, it returns
undefined
.
tsc
in the shinami-examples/movement/typescript/backend_examples
directory to transpile. Then, run node build/gas_station.js
. If successful, you can view the sponsorship on the “Completed transactions” tab of the Movement Gas Station page of your Shinami Dashboard. You can also look up the transaction digest printed to the console in the Movement Explorer (make sure the explorer is set to Testnet).
Appendix
Build a SimpleTransaction for sponsorship
The below function creates a transaction that calls a function on a Move module we’ve deployed to Testnet (it’s from a Movement tutorial). Theset_message
function allows the caller to store a message at their address inside a MessageHolder
struct.
The transaction’s expiration timestamp must be set to a time within the next hour (as is required by our Gas Station). When you control the generation of the sender’s signature, as with an embedded wallet you control for the user, you can likely use the SDK default, which is 20 seconds from now. When you need to wait on a signature you don’t control, as with a connected wallet where the user must approve a signing message, you can explicitly set it.
Build a MultiAgentTransaction with a compiled Move script
Step 1: Building a MultiAgentTransaction for sponsorship. For a multi-agent transaction, you’ll need to provide the secondary signers when building the transaction (in addition to the sender). The transaction’s expiration timestamp must be set to a time within the next hour (as is required by our Gas Station). When you control the generation of the sender’s signature, as with an embedded wallet you control for the user, you can likely use the SDK default, which is 20 seconds from now. When you need to wait on a signature you don’t control, as with a connected wallet where the user must approve a signing message, you can explicitly set it. This function reads a complied Move script inside your local directory and builds a MultiAgentTransaction with it. You’ll need to compile the script to use this function (see “Step 2” below).shinami-examples/movement/typescript/backend_examples/move/sources/unfair_swap_coins.move
cd move
to get to the root of the shinami-examples/movement/typescript/backend_examples/move
directory. Then, run movement move compile
. You should see a build/test/bytecode_scripts/unfair_swap_coins.mv
. That’s the compiled, bytecode version of the below Move script.
This Move script has the sender give the secondary signer 100 Octa in exchange for 200 Octa - not fair! For more guidance on how to run a multi-agent transaction see here, and for guidance on running Move scripts see here.
Generating funded accounts for testing
For the purposes of reusing the same account for repeated tests with this tutorial - which is required when you use one of the functions that takes a funded account as an argument - you can find and reuse a SingleKeyAccount’s private key as shown in the below code (which is near the top of the file). This is just provided for easy testing. Your app should determine the best way to manage any keys it controls, and you should always protect your private keys and not share them. There are three steps, as outlined in the code:1
Uncomment out step 1 (you may want to also comment out other code below that would run, but it’s not necessary). Then, Save changes the file, transpile with
tsc
, and run with node build/gas_station.js
.2
Look at your console for the two addresses printed out. Go to https://faucet.movementnetwork.xyz/ and copying in each address to give it Testnet MOVE. You may need to refresh the page after funding the first address. Note that the faucet currently has a limit of a few requests per day.
3
Comment out step 1. Look at your console for the two private keys printed out. Uncomment step 3 and set one as the value for
PKEY_ONE
and one as the value for PKEY_TWO
. Save changes to the file. Now, the next time you transpile and run the code, you’ll be able to use these two funded accountsSponsoring a transaction for a non-funded account
As our examples above show, you can sponsor a transaction for an Account that has not yet been funded. The transaction fee for an account’s first transaction will cost more than the fee for the same transaction at the same time for a funded account. Example fee statements are below, but your results may vary. Example0x1::transaction_fee::FeeStatement
for a message::setmessage
Testnet Move call sponsored transaction from an unfunded account:
0x1::transaction_fee::FeeStatement
for a message::setmessage
Testnet Move call sponsored transaction from a funded account: