# Deploy and mint a stablecoin

Source: https://docs.settlemint.com/docs/developers/runbooks/create-mint-stablecoins
Create a stablecoin token with the DALP TypeScript client, configure the
required roles and collateral issuer, add collateral, and mint supply.




Deploying a stablecoin requires a contract, system roles, token roles, trusted collateral issuer status, and a recorded collateral claim before minting can proceed. Use the DALP TypeScript client to deploy the contract, configure permissions, record that claim with an expiry timestamp, and mint supply. Fiat reserve custody, treasury approval, and payment-rail settlement stay outside this API path. For the architecture split between DALP-enforced controls and the operator-owned reserve process, see [Stablecoin operating responsibilities](/docs/compliance-security/security/stablecoin-architecture-trust-boundaries).

<Mermaid
  chart="`
flowchart TD
Issuer[&#x22;Stablecoin operator&#x22;] --> Client[&#x22;TypeScript client&#x22;]
Client --> API[&#x22;DALP asset API&#x22;]
API --> Collateral[&#x22;Collateral and reserve policy&#x22;]
API --> Issuers[&#x22;Trusted issuers&#x22;]
API --> Compliance[&#x22;Identity and compliance checks&#x22;]
Collateral --> Contract[&#x22;Stablecoin token contract&#x22;]
Contract --> Holder[&#x22;Holder wallet supply&#x22;]
`"
/>

The diagram traces the path from stablecoin operator through the TypeScript client to the Platform API, where collateral and reserve policy, trusted issuers, and compliance checks feed the token contract. The contract then supplies stablecoins to holder wallets.

## Prerequisites [#prerequisites]

Before you run the script, you need:

1. A running DALP instance and its platform URL, such as `https://your-platform.example.com`.
2. A Platform API key for the account that runs the script.
3. A PIN code configured from **Account → Wallet** in the DALP UI.
4. An account with the `admin` role, or an administrator who can grant the required system roles and trusted issuer status.
5. The wallet address returned by `dalp.user.me({})`. The script uses it when granting token roles and minting to the first holder.

## Quick reference [#quick-reference]

| Step | What                          | Method                                           |
| ---- | ----------------------------- | ------------------------------------------------ |
| 1    | Initialize Client             | `initializeClient`                               |
| 2    | Get user info                 | `userMe`                                         |
| 3    | Set up roles & trusted issuer | Grant `tokenManager`, `claimPolicyManager` roles |
| 4    | Create stablecoin             | `tokenCreate` (type: "stablecoin")               |
| 5    | Grant token roles             | `tokenGrantRole`                                 |
| 6    | Unpause token                 | `tokenUnpause`                                   |
| 7    | Add collateral                | `tokenUpdateCollateral`                          |
| 8    | Mint tokens                   | `tokenMint`                                      |
| 9    | Verify                        | `tokenHolders`                                   |

***

## Stablecoin token lifecycle flow [#stablecoin-token-lifecycle-flow]

The stablecoin path has one additional control: an identity trusted for the collateral claim topic must record collateral, and that record must exist when any mint executes.

<Mermaid
  chart="`flowchart TB
  Init[Initialize Client<br/>initializeClient] --> Auth[Verify Auth<br/>GET /user/me]
  Auth --> Roles[Set Up System Roles<br/>+ Trusted Issuer]
  Roles --> RolesNote[Required:<br/>tokenManager<br/>claimPolicyManager]
  RolesNote --> Create[Create Stablecoin<br/>POST /token/create]
  Create --> Grant[Grant Token Roles<br/>POST /token/:address/grant-role]
  Grant --> Unpause[Unpause Token<br/>PUT /token/:address/unpause]
  Unpause --> Collateral[Add Collateral<br/>PUT /token/:address/update-collateral]
  Collateral --> CollateralNote[Required before<br/>minting stablecoins]
  CollateralNote --> Mint[Mint Stablecoins<br/>POST /token/:address/mint]
  Mint --> Verify[Verify Holders<br/>GET /token/:address/holders]
  
  style Init fill:#5fc9bf,stroke:#3a9d96,stroke-width:2px,color:#fff
  style Auth fill:#6ba4d4,stroke:#4a7ba8,stroke-width:2px,color:#fff
  style Roles fill:#6ba4d4,stroke:#4a7ba8,stroke-width:2px,color:#fff
  style RolesNote fill:#6ba4d4,stroke:#4a7ba8,stroke-width:2px,color:#fff
  style Create fill:#8571d9,stroke:#654bad,stroke-width:2px,color:#fff
  style Grant fill:#8571d9,stroke:#654bad,stroke-width:2px,color:#fff
  style Unpause fill:#8571d9,stroke:#654bad,stroke-width:2px,color:#fff
  style Collateral fill:#8571d9,stroke:#654bad,stroke-width:2px,color:#fff
  style CollateralNote fill:#8571d9,stroke:#654bad,stroke-width:2px,color:#fff
  style Mint fill:#8571d9,stroke:#654bad,stroke-width:2px,color:#fff
  style Verify fill:#b661d9,stroke:#8a3fb3,stroke-width:2px,color:#fff
`"
/>

Stablecoin-specific requirements:

* Trusted issuer registration: register the collateral updater as a trusted issuer for the `collateral` claim topic before adding collateral.
* Collateral update: call `tokenUpdateCollateral` before minting stablecoin supply.
* System roles: use `tokenManager` to create the token and `claimPolicyManager` to manage trusted issuer configuration.
* Token roles: use `supplyManagement` for minting and `emergency` for unpausing.
* Collateral amount: the recorded amount must cover the minted supply under the configured collateral policy.

***

## Step-by-step commands [#step-by-step-commands]

### Step 1: initialise the client [#step-1-initialise-the-client]

Initialise the DALP SDK with your platform URL and API key. The examples import utilities from a shared module described in the expandable section below.

```ts file=<rootDir>/src/examples/create-mint-stablecoin.ts#L1-L10
import { createDalpClient } from "@settlemint/dalp-sdk";

async function main() {
  // Step 1: Create the SDK client
  const dalp = createDalpClient({
    url: "https://your-platform.example.com",
    apiKey: "YOUR_API_KEY",
  });
  const pincode = "YOUR_PINCODE";

```

<details>
  <summary>
    <strong>Client helper implementation details</strong>
  </summary>

  The module wraps common SDK setup and exposes three utilities: `initializeClient(baseUrl, apiKey)` for one-time API authentication, `toBigDecimal()` and `fromBigDecimal()` for precise numeric values, and SDK function re-exports so examples can import API methods directly.

  ```ts file=<rootDir>/src/examples/client.ts
  import { createDalpClient } from "@settlemint/dalp-sdk";

  // Create the SDK client — replace with your actual values
  const dalp = createDalpClient({
    url: "https://your-platform.example.com",
    apiKey: "sm_dalp_xxxxxxxxxxxxxxxx",
  });

  // All methods are fully typed with auto-complete
  const me = await dalp.user.me({});
  console.log("Wallet:", me.data.wallet);

  const tokens = await dalp.token.list({ query: {} });
  console.log("Tokens:", tokens.data.length);
  ```

  Copy `src/examples/client.ts` into your project if you want to reuse the same helper.
</details>

***

### Step 2: check you're logged in [#step-2-check-youre-logged-in]

```ts file=<rootDir>/src/examples/create-mint-stablecoin.ts#L11-L17
  // Step 2: Get your wallet address
  const me = await dalp.user.me({});
  const myWallet = me.data.wallet;
  if (!myWallet) {
    throw new Error("No wallet found. Create a wallet first via the DALP dashboard.");
  }
  console.log("Wallet:", myWallet);
```

Save the returned wallet address. Later steps use it for role grants and minting.

***

### Step 3: set up system roles and trusted issuer status [#step-3-set-up-system-roles-and-trusted-issuer-status]

Complete the role and issuer setup before you create the stablecoin.

1. Grant system roles:
   * `tokenManager`, which allows the caller to create tokens.
   * `claimPolicyManager`, which allows the caller to manage trusted issuer configuration.

2. Register the collateral signer:
   * Add the identity that updates collateral as a trusted issuer for the `collateral` claim topic.

Only a user with the `admin` role can grant system roles. If your API key does not belong to an administrator, ask an administrator to grant the roles and enroll the trusted issuer before continuing.

***

### Step 4: create a stablecoin token [#step-4-create-a-stablecoin-token]

```ts file=<rootDir>/src/examples/create-mint-stablecoin.ts#L23-L39
  // Step 4: Create stablecoin token
  const stablecoin = await dalp.token.create({
    body: {
      type: "stablecoin",
      name: "Test USD Coin",
      symbol: "TUSD",
      decimals: 18,
      countryCode: "840",
      priceCurrency: "USD",
      basePrice: "1.00",
      initialModulePairs: [],
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
```

Parameters:

* `type`: set this to `"stablecoin"`.
* `name`: the token name, such as `"Test USD Coin"`.
* `symbol`: the token symbol, such as `"TUSD"`.
* `decimals`: the precision for token amounts. The example script uses `18`. Use the decimal precision configured for your programme.
* `countryCode`: ISO country code, such as `840` for the United States, `056` for Belgium, or `276` for Germany.
* `priceCurrency`: ISO currency code for liability tracking, such as `"USD"`, `"EUR"`, or `"GBP"`.
* `basePrice`: the peg value for the token, such as `"1.00"`.
* `collateralRatioBps`: the collateral ratio in basis points, from `0` to `20000`. The API default is `10000` (100% backed); `20000` sets the maximum 200% reserve threshold. Use a different value only when your programme needs another policy threshold; `0` disables the collateral ratio check.
* `pegMechanism`: a label for how the peg is maintained. Pass `"fiat-backed"`, `"crypto-backed"`, `"algorithmic"`, or `"commodity-backed"` when known; omit when not applicable.
* `reserveDescription`: a short description of the reserve model for the token record. Keep it factual. Use the reserve asset class, custodian category, or attestation cadence approved for publication.
* `initialModulePairs`: compliance modules. The example uses `[]` for a basic setup.

When creation completes in the same response, DALP returns token data with `id` as the contract address. Save that value; you need it for role grants, collateral recording, minting, and the holder query.

If DALP returns `transactionId` instead, the creation transaction has been queued. Poll `dalp.transaction.status` until the transaction completes. The example script stops at this point because it does not yet have a contract address. After completion, call `dalp.token.list`. Filter by the stablecoin's `name`, `symbol`, and `type` from the create request to locate the new token. Verify the match before copying its contract `id` for role grants, collateral, or mint calls.

The ratio sets the policy threshold. The collateral update step records the amount and expiry evaluated by that policy. `reserveDescription` and token documents give readers context and evidence links. They do not move reserves or prove custody by themselves.

***

### Step 5: grant token roles [#step-5-grant-token-roles]

Grant `supplyManagement` for minting and `emergency` for unpausing on the stablecoin contract.

```ts file=<rootDir>/src/examples/create-mint-stablecoin.ts#L48-L70
  // Step 5: Grant token roles
  await dalp.token.grantRole({
    params: { tokenAddress },
    body: {
      accounts: [myWallet],
      role: "supplyManagement",
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
  await dalp.token.grantRole({
    params: { tokenAddress },
    body: {
      accounts: [myWallet],
      role: "emergency",
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
```

***

### Step 6: unpause the token [#step-6-unpause-the-token]

```ts file=<rootDir>/src/examples/create-mint-stablecoin.ts#L73-L82
  // Step 6: Unpause the stablecoin
  await dalp.token.unpause({
    params: { tokenAddress },
    body: {
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
```

***

### Step 7: add collateral (required for stablecoins) [#step-7-add-collateral-required-for-stablecoins]

Stablecoin minting requires a collateral record first. The account that adds it must already be trusted for the `collateral` claim topic.

```ts file=<rootDir>/src/examples/create-mint-stablecoin.ts#L85-L99
  // Step 7: Add collateral (Required for stablecoins)
  const expiryDate = new Date();
  expiryDate.setFullYear(expiryDate.getFullYear() + 1);

  await dalp.token.updateCollateral({
    params: { tokenAddress },
    body: {
      amount: 1_000_000_000_000_000_000_000_000n,
      expiryTimestamp: expiryDate.toISOString(),
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
```

Parameters:

* `amount`: collateral amount in the token's smallest unit. Match this to the token decimals you configured.
* `expiryTimestamp`: ISO 8601 timestamp for when the collateral claim expires.

The call returns token data with updated collateral. If DALP reports that the caller is not a trusted issuer, complete the trusted issuer setup for the `collateral` claim topic before retrying.

***

### Step 8: mint stablecoins [#step-8-mint-stablecoins]

```ts file=<rootDir>/src/examples/create-mint-stablecoin.ts#L102-L113
  // Step 8: Mint stablecoins — 1000 TUSD
  await dalp.token.mint({
    params: { tokenAddress },
    body: {
      recipients: [myWallet],
      amounts: [1_000_000_000_000_000_000_000n],
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
```

Parameters:

* `contract`: the stablecoin contract address.
* `recipients`: recipient wallet addresses.
* `amounts`: amounts in the token's smallest unit. For the 18-decimal example script, `1_000_000_000_000_000_000_000n` represents 1,000 tokens.

The call returns token data with updated `totalSupply`.

***

### Step 9: verify the mint [#step-9-verify-the-mint]

```ts file=<rootDir>/src/examples/create-mint-stablecoin.ts#L116-L118
  // Step 9: Verify holders
  const holders = await dalp.token.holders({ params: { tokenAddress }, query: { limit: 200 } });
  console.log("Holders:", holders.data);
```

The holder query returns wallets and balances for the token.

***

## Full script [#full-script]

Replace `YOUR_PLATFORM_URL`, `YOUR_API_KEY`, and `YOUR_PINCODE` in the full example before you run it.

Step 3 is a placeholder because role and trusted issuer setup requires administrator access. Finish the `tokenManager`, `claimPolicyManager`, and collateral trusted issuer setup before running the rest of the example. If you do not have admin access, ask an administrator to finish those steps.

```ts file=<rootDir>/src/examples/create-mint-stablecoin.ts
import { createDalpClient } from "@settlemint/dalp-sdk";

async function main() {
  // Step 1: Create the SDK client
  const dalp = createDalpClient({
    url: "https://your-platform.example.com",
    apiKey: "YOUR_API_KEY",
  });
  const pincode = "YOUR_PINCODE";

  // Step 2: Get your wallet address
  const me = await dalp.user.me({});
  const myWallet = me.data.wallet;
  if (!myWallet) {
    throw new Error("No wallet found. Create a wallet first via the DALP dashboard.");
  }
  console.log("Wallet:", myWallet);

  // Step 3: Set up system roles and trusted issuer status
  // Grant yourself 'tokenManager' and 'claimPolicyManager'
  // Register as a trusted issuer for the 'collateral' claim topic

  // Step 4: Create stablecoin token
  const stablecoin = await dalp.token.create({
    body: {
      type: "stablecoin",
      name: "Test USD Coin",
      symbol: "TUSD",
      decimals: 18,
      countryCode: "840",
      priceCurrency: "USD",
      basePrice: "1.00",
      initialModulePairs: [],
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });

  if ("transactionId" in stablecoin) {
    console.log("Stablecoin creation queued:", stablecoin.transactionId);
    return;
  }
  const tokenAddress = stablecoin.data.id;
  console.log("Stablecoin created:", tokenAddress);

  // Step 5: Grant token roles
  await dalp.token.grantRole({
    params: { tokenAddress },
    body: {
      accounts: [myWallet],
      role: "supplyManagement",
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
  await dalp.token.grantRole({
    params: { tokenAddress },
    body: {
      accounts: [myWallet],
      role: "emergency",
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
  console.log("Roles granted");

  // Step 6: Unpause the stablecoin
  await dalp.token.unpause({
    params: { tokenAddress },
    body: {
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
  console.log("Stablecoin unpaused");

  // Step 7: Add collateral (Required for stablecoins)
  const expiryDate = new Date();
  expiryDate.setFullYear(expiryDate.getFullYear() + 1);

  await dalp.token.updateCollateral({
    params: { tokenAddress },
    body: {
      amount: 1_000_000_000_000_000_000_000_000n,
      expiryTimestamp: expiryDate.toISOString(),
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
  console.log("Collateral added");

  // Step 8: Mint stablecoins — 1000 TUSD
  await dalp.token.mint({
    params: { tokenAddress },
    body: {
      recipients: [myWallet],
      amounts: [1_000_000_000_000_000_000_000n],
      walletVerification: {
        secretVerificationCode: pincode,
        verificationType: "PINCODE",
      },
    },
  });
  console.log("Minted stablecoins");

  // Step 9: Verify holders
  const holders = await dalp.token.holders({ params: { tokenAddress }, query: { limit: 200 } });
  console.log("Holders:", holders.data);
}

await main();
```

## Common country codes [#common-country-codes]

* 840 = USA
* 056 = Belgium
* 276 = Germany
* 826 = UK
* 392 = Japan

***

## Backing evidence routing [#backing-evidence-routing]

For asset-backed stablecoins, keep three records consistent:

| Record            | What DALP stores                                                                                              | What remains outside DALP                                                                            |
| ----------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Stablecoin fields | Peg currency, peg value, optional peg mechanism, optional reserve description, and collateral ratio policy.   | The legal, treasury, and custody decision that the reserve exists and can back the issued token.     |
| Collateral claim  | Amount and expiry attested by a trusted collateral issuer. DALP checks this claim before minting.             | The issuer's review of bank, custodian, trustee, warehouse, or auditor evidence.                     |
| Token documents   | Asset evidence files such as `reserve_audit`, `attestation_report`, or `reserve_composition` for stablecoins. | Whether those files are sufficient for a regulator, investor, custodian, or internal approval forum. |

Upload attestation documents via [token document uploads](/docs/api-reference/tokens/token-documents). The [collateral compliance controls](/docs/developers/compliance/collateral) page covers the claim that DALP enforces during minting. For the full split between DALP-controlled mint checks and reserve custody, treasury approval, payment rails, accounting, and audit evidence, see [Stablecoin operating responsibilities](/docs/compliance-security/security/stablecoin-architecture-trust-boundaries).

## Amount calculations [#amount-calculations]

DALP expects mint and collateral amounts in the token's smallest unit, calculated as `token amount * 10^decimals`. The two examples below cover the precisions used in this runbook.

```text
token amount * 10^decimals
```

With 6 decimal places, 1 token = `1 * 10^6` = `1000000` and 1,000 tokens = `1000 * 10^6` = `1000000000`.

With 18 decimal places (as in the example script), 1 token = `1 * 10^18` = `1000000000000000000` and 1,000 tokens = `1000 * 10^18` = `1000000000000000000000`.

***

![Stablecoin listing with collateral information](/docs/screenshots/stablecoins/stablecoins.webp)

## Troubleshooting [#troubleshooting]

| Error or symptom                                          | Fix                                                                                                                                                                                  |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `"Authentication missing"`                                | Check the API key passed to `initializeClient`.                                                                                                                                      |
| `"PINCODE_INVALID"`                                       | Reconfirm the PIN from **Account → Wallet** (`/account/wallet`).                                                                                                                     |
| `"USER_NOT_AUTHORIZED"` or `"tokenManager required"`      | Grant the `tokenManager` role. This requires admin access.                                                                                                                           |
| `"Permission denied"`                                     | Grant the required token roles: `supplyManagement` for minting, `emergency` for unpausing.                                                                                           |
| `"Token is paused"`                                       | Confirm Step 6 succeeded and the caller holds the `emergency` role.                                                                                                                  |
| `"InsufficientCollateral"`                                | Confirm Step 7 succeeded. The recorded collateral must cover the mint amount under the configured ratio policy. Increase the collateral claim or reduce the mint amount, then retry. |
| `"You are not a trusted issuer for topic(s): collateral"` | Register the collateral updater as a trusted issuer for the collateral claim topic.                                                                                                  |
| `"RecipientNotVerified"`                                  | The recipient wallet needs an identity before it can receive tokens. Register the identity with `systemIdentityCreate`.                                                              |

`jq` is optional for local scripting. Install it with `brew install jq` on macOS or `apt install jq` on Linux if you want to parse JSON responses in shell commands.

## Related [#related]

* [Stablecoin operating responsibilities](/docs/compliance-security/security/stablecoin-architecture-trust-boundaries)
* [Stablecoin use case](/docs/business/use-cases/stablecoins)
* [Collateral compliance controls](/docs/developers/compliance/collateral)
* [Token document uploads](/docs/api-reference/tokens/token-documents)
* [Configure trusted issuers](/docs/developers/compliance/configure-trusted-issuers)
* [Mint assets](/docs/developers/asset-servicing/mint-assets)
