Sending a transaction through the API typically requires an authenticated user to make the request from the client side. However, the nature of Treasure Connect’s on-chain session creation also allows games to act on a Treasure Account’s behalf through the backend only for the duration and scope of the previously-approved session.

This flow is best if the on-chain transaction needs to originate from the end user (i.e., msg.sender in a Solidity contract resolves to the user’s Treasure Account). If the sender is not important (e.g., airdrops, admin game updates, etc.) consider sending transactions as the backend.

Setup

1

Get backend wallet

Check in with the Treasure team to receive your backend wallet address (used in your app client and backend) and AWS KMS key ARN (used in the next step and your backend).

2

Create AWS role

Create a new IAM role in your AWS account with the following policy attached, filling in the AWS KMS key ARN from the previous step:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowKmsTdkBackendWalletAccess",
            "Effect": "Allow",
            "Action": [
                "kms:GetPublicKey",
                "kms:Verify",
                "kms:Sign"
            ],
            "Resource": "<awsKmsKeyArn>"
        }
    ]
}

Provide the Treasure team with the new role’s ARN to complete the setup process.

Prerequisites

  • TDK Core library installed in your project.
  • The Treasure Account you want to act on behalf of must have already created a session through the client-side TDK with the same backendWallet address that will be used to sign the backend-to-backend request. See here for more information on starting sessions from a React-based application.

Usage

import { generateAccountSignature, TDKAPI } from "@treasure-dev/tdk-core";

// The Treasure Account address you want to act on behalf of
const accountAddress = "...";

// The AWS KMS key ARN provided by the Treasure team
const kmsKey = "...";

const { backendWallet, signature, expirationTime } =
  await generateAccountSignature({
    accountAddress,
    kmsKey,
  });

const tdk = new TDKAPI({
  baseUri: "https://tdk-api.spellcaster.lol",
  chainId: 421614,
  backendWallet,
});

await tdk.transaction.create(
  {
    address: "0x55d0cf68a1afe0932aff6f36c87efa703508191c",
    abi: [
      {
        type: "function",
        name: "transfer",
        stateMutability: "nonpayable",
        inputs: [
          {
            name: "recipient",
            type: "address",
          },
          {
            name: "amount",
            type: "uint256",
          },
        ],
        outputs: [
          {
            type: "bool",
          },
        ],
      },
    ] as const,
    functionName: "transfer",
    args: [
      "...", // recipient address
      1000000000000000000000n, // 1,000
    ],
  },
  {
    accountAddress,
    accountSignature: signature,
    accountSignatureExpiration: expirationTime,
  },
);

The key change in the above flow is that the TDKAPI client doesn’t need to be created with a user’s auth token. Instead, the account address is specified in the transaction options, along with a payload signed by the backend wallet that will be verified by the TDK API.

If using direct API requests instead of the TDKAPI client, please provide the accountAddress in the X-Account-Address header, the signature in the X-Account-Signature header and the expirationTime in the X-Account-Signature-Expiration header.

See full generateAccountSignature function documentation for more AWS KMS client configuration options.

Example

An example script showcasing this process is available on GitHub.