Skip to content

Create a LOC

Outcome: a Static LOC exists on Sepolia, with collateral reserved for your named Beneficiary until the expiration you set.

You need: the read setup plus a wallet with Sepolia test ETH and a supported test token to reserve as collateral. This is the partner-preview testnet, so use test assets only.

Every write follows the same three steps: validate the parameters with no wallet involved, build a workflow (the SDK works out which deposit, approval, and signature steps the wallet needs), then execute it.

import { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { sepolia } from 'viem/chains';
import {
AnvilSDK,
type CreateStaticLOCParams,
testnetProfile,
} from '@anvil/sdk/core';
const transport = http('https://your-rpc-url');
const account = privateKeyToAccount('0xyour-private-key');
const sdk = new AnvilSDK({
publicClient: createPublicClient({ chain: sepolia, transport }),
walletClient: createWalletClient({ account, chain: sepolia, transport }),
// The testnet profile binds each protocol address to the interface
// deployed there.
profile: testnetProfile,
});
const params: CreateStaticLOCParams = {
beneficiary: '0xBeneficiaryAddress',
tokenAmount: { tokenAddress: '0xTokenAddress', amount: 1_000_000n },
expirationTimestampSeconds: BigInt(
Math.floor(Date.now() / 1000) + 86400 * 30
),
};
// Validate before touching the wallet — an empty array means the params
// are valid.
const issues = await sdk.loc.validateCreateStatic(params);
if (issues.length === 0) {
const workflow = await sdk.loc.buildCreateStaticWorkflow(params);
const execution = await workflow.execute();
console.log(execution);
}

What the SDK handles, and what your app handles

  • The SDK works out the steps and submits each one through your walletClient: an ERC-20 approval when the Collateral Vault’s allowance is short, a vault deposit when your vault balance can’t cover the collateral, a typed-data signature authorizing the LetterOfCredit contract to reserve that collateral when one is needed, then the create transaction. When your balances and allowances already cover it, the workflow is the create transaction alone. workflow.operations lists the planned steps in order before anything runs.
  • Your app owns the wallet experience. The wallet prompts once per step, so show progress as each one completes. execute() first validates again against fresh state. Its executed outcome carries the completed operations: transaction steps carry a transactionHash, and a signature step carries signature. The invalid, failed, and cancelled outcomes open no new prompt and leave queued steps as they were.
  • Anyone can verify the result. Read the LOC back with sdk.loc.getOutstandingLetterOfCredit and check the creation transaction on Etherscan. Subgraph-backed listings show the new LOC once the subgraph has indexed the transaction.

A Static LOC uses the same token for collateral and credit, one to one. A Dynamic LOC uses a different collateral token, priced by the Pyth oracle (LOC Types). CreateDynamicLOCParams and Collateral and risk cover what a Dynamic LOC adds.