Code Samples
Copy-paste examples for common Dual workflows in TypeScript, Python, and cURL.
Authenticate & Get Current Wallet
TypeScript SDK
Code
import { DualClient } from "dual-sdk";// Using API Keyconst client = new DualClient({token: process.env.DUAL_API_KEY,authMode: 'api_key'});// Using Bearer JWT Tokenconst clientBearer = new DualClient({token: process.env.DUAL_JWT_TOKEN,authMode: 'bearer'});const wallet = await client.wallets.me();console.log(wallet.address);
Python SDK
Code
from dual_sdk import DualClient# Using API Keyclient = DualClient(token=os.environ["DUAL_API_KEY"],auth_mode="api_key")# Using Bearer JWT Tokenclient_bearer = DualClient(token=os.environ["DUAL_JWT_TOKEN"],auth_mode="bearer")wallet = client.wallets.me()print(wallet.address)
cURL with API Key
Code
curl -H "x-api-key: $DUAL_API_KEY" \\https://api-testnet.dual.network/wallets/me
cURL with Bearer Token
Code
curl -H "Authorization: Bearer $DUAL_JWT_TOKEN" \\https://api-testnet.dual.network/wallets/me
Create a Template & Mint an Object
TypeScript SDK
Code
// 1. Create templateconst template = await client.templates.create({name: "Concert Ticket",description: "Tokenized concert ticket",properties: {event_name: "string",tier: "string",redeemed: "boolean",},});// 2. Mint object using ebus actionconst action = await client.eventBus.execute({actionType: "emit",templateId: template.id,properties: {event_name: "Summer Festival 2026",tier: "general",redeemed: false,seat: "GA-042",},});const ticket = await client.objects.get(action.objectId);
Python SDK
Code
from dual_sdk import DualClientclient = DualClient(token=os.environ["DUAL_API_KEY"],auth_mode="api_key")# 1. Create templatetemplate = client.templates.create({"name": "Concert Ticket","description": "Tokenized concert ticket","properties": {"event_name": "string","tier": "string","redeemed": "boolean",},})# 2. Mint object using ebus actionaction = client.event_bus.execute({"action_type": "emit","template_id": template["id"],"properties": {"event_name": "Summer Festival 2026","tier": "general","redeemed": False,"seat": "GA-042",},})ticket = client.objects.get(action["object_id"])
Transfer an Object
Code
// TypeScriptawait client.eventBus.execute({actionType: "transfer",objectId: ticket.id,payload: { to: "0xRecipientAddress" },});// Pythonclient.event_bus.execute({"action_type": "transfer","object_id": ticket.id,"payload": {"to": "0xRecipientAddress"},})
Search Objects by Property
Code
// TypeScriptconst vipTickets = await client.objects.search({templateId: template.id,properties: { tier: "vip" },limit: 50,});# Pythonfrom dual_sdk import ObjectQueryvip_tickets = client.objects.search(ObjectQuery(template_id=template.id,properties={"tier": "vip"},limit=50,))
Listen for Webhooks
Always verify webhook signatures using HMAC-SHA256 before processing events:
Code
import * as crypto from "crypto";import express from "express";const webhookSecret = process.env.DUAL_WEBHOOK_SECRET;const app = express();app.use(express.json());// Express.js webhook handler with signature verificationapp.post("/webhooks/dual", (req, res) => {// 1. Verify signatureconst signature = req.headers["x-dual-signature"] as string;const timestamp = req.headers["x-dual-timestamp"] as string;const body = JSON.stringify(req.body);const message = \`\${timestamp}.\${body}\`;const expectedSignature = crypto.createHmac("sha256", webhookSecret).update(message).digest("hex");if (signature !== expectedSignature) {console.error("Invalid webhook signature!");return res.status(401).send("Unauthorized");}// 2. Process eventconst { event, payload } = req.body;switch (event) {case "object.created":console.log("New object:", payload.object_id);break;case "object.transferred":console.log("Transfer:", payload.from, "→", payload.to);break;}res.sendStatus(200);});
Upload an Asset to Storage
Code
# Python, upload an image and attach it to a templateurl = client.storage.upload("ticket_artwork.png", open("artwork.png", "rb"))client.templates.update(template.id, {"properties": {"image_url": url}})