# Executing a transaction

To demonstrate MagicSpend++, we’ll walk through a simple, real-world EVM transaction: transferring 1.0 USDC on Polygon. This compact example shows the full flow end-to-end—constructing ERC‑20 transfer calldata from the USDC ABI, requesting a canonical userOp hash from the backend, signing that hash with a Turnkey-backed account, producing EIP‑7702 authorization(s), and finally submitting everything to a submit endpoint.&#x20;

By following this sequence, you’ll see how MagicSpend++ enables chain abstracted execution with minimal friction while keeping the signer experience familiar.

### Step 1 — Build ERC‑20 Transfer Transaction Calldata

{% tabs %}
{% tab title="Viem" %}

<pre class="language-javascript"><code class="lang-javascript"><strong>import { erc20Abi, encodeFunctionData, parseUnits } from 'viem';
</strong>
const chainId = 137;
const usdc = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174';
const recipient = '0x1111111111111111111111111111111111111111';

// 1. Convert 1.0 USDC to base units (6 decimals)
const amount = parseUnits('1.0', 6);

// 2. Encode transfer(to, amount) calldata
const encodedData = encodeFunctionData({
  abi: erc20Abi,
  functionName: 'transfer',
  args: [recipient, amount],
});
</code></pre>

{% endtab %}

{% tab title="Ethers" %}

```javascript
import { Interface, parseUnits } from 'ethers';

const chainId = 137;
const usdc = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174';
const recipient = '0x1111111111111111111111111111111111111111';

const erc20 = new Interface([
  'function transfer(address to, uint256 amount) returns (bool)'
]);

const amount = parseUnits('1.0', 6); // 1 USDC -> 1_000_000
const encodedData = erc20.encodeFunctionData('transfer', [recipient, amount]);
```

{% endtab %}
{% endtabs %}

#### Step 2 — Build the chain abstracted transaction (with quote type + token addresses)

```javascript
import axios from 'axios';

const chainId = 137; // Polygon

// Token the user settles in
const settlementToken = 'USDC'; 

// Token the user spends
const spendingTokenAddress = '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174';

// For a transfer, spending and settlement tokens are both USDC.
// Use 'AMOUNT_OUT' to send an exact recipient amount; 'AMOUNT_IN' to spend an exact input amount.
const quoteType = 'AMOUNT_OUT'; // or 'AMOUNT_IN'
const amount = '1000000'; // Formatted amount (USDC uses 6 decimals)

const { data: transactionData } = await axios.post('https://api.enclave.money/magicspend/build-transaction', {
  chainId,
  transactions: [{
    to: usdc
    
    // encodedData comes from Step 1 (ERC-20 transfer calldata built via viem/ethers)
    data: encodedData
  }],
  quoteType, // 'AMOUNT_OUT' | 'AMOUNT_IN'
  amount, // '1.0' => 1 USDC
  spendingTokenAddress,   // token user spends
  settlementToken // token user settle in (ex. 'USDC' or 'SOL')
}, {
  headers: {
    'Content-Type': 'application/json',
    'Authorization': process.env.ENCLAVE_API_KEY,
  }
});

const { 
  userOpHash, 
  authorizations, 
  settlementPlan, 
  expiryTimestamp, 
  transactionId 
} = transactionData;
```

**Supported Settlement Tokens**

| Token | Identifier | Supported Networks                                                                                                 |
| ----- | ---------- | ------------------------------------------------------------------------------------------------------------------ |
| USDC  | USDC       | Ethereum Mainnet, Arbitrum, Base, Optimism, Polygon, Avalanche, Unichain, Binance Smart Chain, World Chain, Solana |
| SOL   | SOL        | Solana                                                                                                             |
| ETH   | ETH        | Ethereum Mainnet, Arbitrum, Base, Optimism, Polygon, Unichain, World Chain                                         |

### Step 3 - Initialize turnkey and sign the user operation and authorizations

```javascript
import { Turnkey as TurnkeyServerSDK } from '@turnkey/sdk-server';
import { createAccount } from '@turnkey/viem';
import { createWalletClient, http } from 'viem';
import { polygon } from 'viem/chains';

const turnkeyClient = new TurnkeyServerSDK({
  apiBaseUrl: 'https://api.turnkey.com',
  apiPrivateKey: process.env.NEXT_PUBLIC_ENCLAVE_DELEGATE_API_PRIVATE_KEY!,
  apiPublicKey: process.env.NEXT_PUBLIC_ENCLAVE_DELEGATE_API_PUBLIC_KEY!,
});

const organizationId = 'USER_SUB_ORG_ID';
const userTurnkeyEvmAddress = '0xUserAddress';
const rpcUrl = '<YOUR_RPC_URL>';

const account = await createAccount({
  client: turnkeyClient.apiClient(),
  organizationId,
  signWith: userTurnkeyEvmAddress,
});

const walletClient = createWalletClient({
  account,
  chain: polygon,
  transport: http(rpcUrl),
});

const userOpSignature = await walletClient.signMessage({
  account: walletClient.account,
  message: { raw: userOpHash },
});
```

### Step 4 — Sign EIP‑7702 authorization(s)

```javascript
// Sign each authorization
const authorizationList = await Promise.all(
  authorizations.map((authorization: { contractAddress, chainId, nonce }) =>
    walletClient.signAuthorization({
      ...authorization,
      account: walletClient.account,
    })
  )
);
```

### Step 5 - Submitting the transaction

```javascript
// Submitting transaction response
const { data: submitResponse } = await axios.post('https://api.enclave.money/magicspend/submit', {
  transactionId,
  userOpSignature,
  authorizationList,
}, {
  headers: {
    'Content-Type': 'application/json',
    'Authorization': process.env.ENCLAVE_API_KEY,
  }
});

const { txHash, transactionId, status } = submitResponse
```

### Step 6 - Checking the status of the transaction

```javascript
const { 
    status, 
    failureReason, 
    executedAt, 
    settledAt, 
    targetTransaction, 
    settlementTransactions  
} = await axios.get('https://api.enclave.money/magicspend/tx-status', 
    { params: { transactionId } },
    {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': process.env.ENCLAVE_API_KEY,
    }
});
// Example: { status: 'PENDING' | 'SUBMITTED' | 'TARGET_EXECUTED' | 'SETTLING | 'SETTLEMENT_EXECUTED' | 'EXPIRED' | 'FAILED' }
console.log('Transaction Status:', status);
```

**Status Codes**

| Status Code          | Description                                                                                                 |
| -------------------- | ----------------------------------------------------------------------------------------------------------- |
| PENDING              | Transaction is built but signatures for the transaction have not been submitted yet                         |
| SUBMITTED            | Transaction has been submitted and the user's desired action will be executed on the target chain           |
| TARGET\_EXECUTED     | Target chain transaction has been succeefully executed. Settlement of the transaction is now pending.       |
| SETTLING             | Settlement transactions on each of the settlement chains have been submitted and pending execution          |
| SETTLEMENT\_EXECUTED | Settlement transactions on all settlement chains have been executed                                         |
| EXPIRED              | Transaction was built but was not submitted on time for valid execution                                     |
| FAILED               | Transaction execution failed. This may be due to a reverted transaction on the target or settlement chains. |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.enclave.money/introducing-enclave-money/magicspend++/getting-started-with-turnkey/executing-a-transaction.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
