x402-engineer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT.md +102 -0
- package/README.md +43 -0
- package/dist/cli.cjs +137 -0
- package/package.json +51 -0
- package/skills/stellar-dev/SKILL.md +146 -0
- package/skills/stellar-dev/advanced-patterns.md +188 -0
- package/skills/stellar-dev/api-rpc-horizon.md +521 -0
- package/skills/stellar-dev/common-pitfalls.md +510 -0
- package/skills/stellar-dev/contracts-soroban.md +565 -0
- package/skills/stellar-dev/ecosystem.md +430 -0
- package/skills/stellar-dev/frontend-stellar-sdk.md +651 -0
- package/skills/stellar-dev/resources.md +306 -0
- package/skills/stellar-dev/security.md +491 -0
- package/skills/stellar-dev/standards-reference.md +94 -0
- package/skills/stellar-dev/stellar-assets.md +419 -0
- package/skills/stellar-dev/testing.md +786 -0
- package/skills/stellar-dev/zk-proofs.md +136 -0
- package/skills/x402-add-paywall/SKILL.md +208 -0
- package/skills/x402-add-paywall/references/patterns.md +132 -0
- package/skills/x402-debug/SKILL.md +92 -0
- package/skills/x402-debug/references/checklist.md +146 -0
- package/skills/x402-explain/SKILL.md +136 -0
- package/skills/x402-init/SKILL.md +129 -0
- package/skills/x402-init/templates/env-example.md +17 -0
- package/skills/x402-init/templates/express/config.ts.md +29 -0
- package/skills/x402-init/templates/express/server.ts.md +30 -0
- package/skills/x402-init/templates/fastify/adapter.ts.md +66 -0
- package/skills/x402-init/templates/fastify/config.ts.md +29 -0
- package/skills/x402-init/templates/fastify/server.ts.md +90 -0
- package/skills/x402-init/templates/hono/config.ts.md +29 -0
- package/skills/x402-init/templates/hono/server.ts.md +31 -0
- package/skills/x402-init/templates/next-app-router/config.ts.md +29 -0
- package/skills/x402-init/templates/next-app-router/server.ts.md +31 -0
- package/skills/x402-stellar/SKILL.md +139 -0
- package/skills/x402-stellar/references/api.md +237 -0
- package/skills/x402-stellar/references/patterns.md +276 -0
- package/skills/x402-stellar/references/setup.md +138 -0
- package/skills/x402-stellar/scripts/check-deps.js +218 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
# Stellar Assets (Classic + Soroban Interop)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Stellar has two token mechanisms:
|
|
6
|
+
|
|
7
|
+
1. **Stellar Assets (Classic)**: Built-in, highly efficient, full ecosystem support
|
|
8
|
+
2. **Soroban Tokens**: Custom contracts with flexible logic
|
|
9
|
+
|
|
10
|
+
**Recommendation**: Prefer Stellar Assets unless you need custom token logic.
|
|
11
|
+
|
|
12
|
+
## Stellar Assets (Classic)
|
|
13
|
+
|
|
14
|
+
### Asset Types
|
|
15
|
+
|
|
16
|
+
| Type | Description |
|
|
17
|
+
|------|-------------|
|
|
18
|
+
| Native (XLM) | Stellar's native currency, no trustline needed |
|
|
19
|
+
| Credit | Issued by an account, requires trustline |
|
|
20
|
+
| Liquidity Pool Shares | Represent LP positions |
|
|
21
|
+
|
|
22
|
+
### Asset Identifiers
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import * as StellarSdk from "@stellar/stellar-sdk";
|
|
26
|
+
|
|
27
|
+
// Native XLM
|
|
28
|
+
const xlm = StellarSdk.Asset.native();
|
|
29
|
+
|
|
30
|
+
// Credit asset (code + issuer)
|
|
31
|
+
const usdc = new StellarSdk.Asset(
|
|
32
|
+
"USDC",
|
|
33
|
+
"GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// Asset code rules:
|
|
37
|
+
// - 1-4 chars: alphanumeric (credit_alphanum4)
|
|
38
|
+
// - 5-12 chars: alphanumeric (credit_alphanum12)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Issuing Assets
|
|
42
|
+
|
|
43
|
+
### Create Issuing Account
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import * as StellarSdk from "@stellar/stellar-sdk";
|
|
47
|
+
|
|
48
|
+
const server = new StellarSdk.Horizon.Server("https://horizon-testnet.stellar.org");
|
|
49
|
+
|
|
50
|
+
// 1. Create issuing account (should be separate from distribution)
|
|
51
|
+
const issuerKeypair = StellarSdk.Keypair.random();
|
|
52
|
+
const distributorKeypair = StellarSdk.Keypair.random();
|
|
53
|
+
|
|
54
|
+
// 2. Fund accounts (testnet)
|
|
55
|
+
await fetch(`https://friendbot.stellar.org?addr=${issuerKeypair.publicKey()}`);
|
|
56
|
+
await fetch(`https://friendbot.stellar.org?addr=${distributorKeypair.publicKey()}`);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Issue Asset
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
const asset = new StellarSdk.Asset("MYTOKEN", issuerKeypair.publicKey());
|
|
63
|
+
|
|
64
|
+
// 1. Distributor creates trustline to issuer
|
|
65
|
+
const distributorAccount = await server.loadAccount(distributorKeypair.publicKey());
|
|
66
|
+
|
|
67
|
+
const trustlineTx = new StellarSdk.TransactionBuilder(distributorAccount, {
|
|
68
|
+
fee: StellarSdk.BASE_FEE,
|
|
69
|
+
networkPassphrase: StellarSdk.Networks.TESTNET,
|
|
70
|
+
})
|
|
71
|
+
.addOperation(
|
|
72
|
+
StellarSdk.Operation.changeTrust({
|
|
73
|
+
asset: asset,
|
|
74
|
+
limit: "1000000", // Max amount to hold
|
|
75
|
+
})
|
|
76
|
+
)
|
|
77
|
+
.setTimeout(180)
|
|
78
|
+
.build();
|
|
79
|
+
|
|
80
|
+
trustlineTx.sign(distributorKeypair);
|
|
81
|
+
await server.submitTransaction(trustlineTx);
|
|
82
|
+
|
|
83
|
+
// 2. Issuer sends tokens to distributor
|
|
84
|
+
const issuerAccount = await server.loadAccount(issuerKeypair.publicKey());
|
|
85
|
+
|
|
86
|
+
const issueTx = new StellarSdk.TransactionBuilder(issuerAccount, {
|
|
87
|
+
fee: StellarSdk.BASE_FEE,
|
|
88
|
+
networkPassphrase: StellarSdk.Networks.TESTNET,
|
|
89
|
+
})
|
|
90
|
+
.addOperation(
|
|
91
|
+
StellarSdk.Operation.payment({
|
|
92
|
+
destination: distributorKeypair.publicKey(),
|
|
93
|
+
asset: asset,
|
|
94
|
+
amount: "1000000",
|
|
95
|
+
})
|
|
96
|
+
)
|
|
97
|
+
.setTimeout(180)
|
|
98
|
+
.build();
|
|
99
|
+
|
|
100
|
+
issueTx.sign(issuerKeypair);
|
|
101
|
+
await server.submitTransaction(issueTx);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Lock Issuing Account
|
|
105
|
+
|
|
106
|
+
For fixed-supply tokens, lock the issuer:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
const lockTx = new StellarSdk.TransactionBuilder(issuerAccount, {
|
|
110
|
+
fee: StellarSdk.BASE_FEE,
|
|
111
|
+
networkPassphrase: StellarSdk.Networks.TESTNET,
|
|
112
|
+
})
|
|
113
|
+
.addOperation(
|
|
114
|
+
StellarSdk.Operation.setOptions({
|
|
115
|
+
masterWeight: 0, // Disable master key
|
|
116
|
+
})
|
|
117
|
+
)
|
|
118
|
+
.setTimeout(180)
|
|
119
|
+
.build();
|
|
120
|
+
|
|
121
|
+
lockTx.sign(issuerKeypair);
|
|
122
|
+
await server.submitTransaction(lockTx);
|
|
123
|
+
// Issuer can never issue more tokens
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Asset Flags
|
|
127
|
+
|
|
128
|
+
Configure issuer account flags for compliance:
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
const setFlagsTx = new StellarSdk.TransactionBuilder(issuerAccount, {
|
|
132
|
+
fee: StellarSdk.BASE_FEE,
|
|
133
|
+
networkPassphrase: StellarSdk.Networks.TESTNET,
|
|
134
|
+
})
|
|
135
|
+
.addOperation(
|
|
136
|
+
StellarSdk.Operation.setOptions({
|
|
137
|
+
setFlags:
|
|
138
|
+
StellarSdk.AuthRequiredFlag | // Trustlines require approval
|
|
139
|
+
StellarSdk.AuthRevocableFlag | // Can freeze trustlines
|
|
140
|
+
StellarSdk.AuthClawbackEnabledFlag, // Can clawback tokens
|
|
141
|
+
})
|
|
142
|
+
)
|
|
143
|
+
.setTimeout(180)
|
|
144
|
+
.build();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Flag Descriptions
|
|
148
|
+
|
|
149
|
+
| Flag | Effect |
|
|
150
|
+
|------|--------|
|
|
151
|
+
| `AUTH_REQUIRED` | Users must get approval before receiving tokens |
|
|
152
|
+
| `AUTH_REVOCABLE` | Issuer can freeze user balances |
|
|
153
|
+
| `AUTH_IMMUTABLE` | Flags cannot be changed (permanent) |
|
|
154
|
+
| `AUTH_CLAWBACK_ENABLED` | Issuer can clawback tokens from accounts |
|
|
155
|
+
|
|
156
|
+
### Authorize Trustline
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
// When AUTH_REQUIRED is set, approve trustlines:
|
|
160
|
+
const authorizeTx = new StellarSdk.TransactionBuilder(issuerAccount, {
|
|
161
|
+
fee: StellarSdk.BASE_FEE,
|
|
162
|
+
networkPassphrase: StellarSdk.Networks.TESTNET,
|
|
163
|
+
})
|
|
164
|
+
.addOperation(
|
|
165
|
+
StellarSdk.Operation.setTrustLineFlags({
|
|
166
|
+
trustor: userPublicKey,
|
|
167
|
+
asset: asset,
|
|
168
|
+
flags: {
|
|
169
|
+
authorized: true,
|
|
170
|
+
// authorizedToMaintainLiabilities: true, // Partial auth
|
|
171
|
+
},
|
|
172
|
+
})
|
|
173
|
+
)
|
|
174
|
+
.setTimeout(180)
|
|
175
|
+
.build();
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Clawback Tokens
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// Requires AUTH_CLAWBACK_ENABLED flag
|
|
182
|
+
const clawbackTx = new StellarSdk.TransactionBuilder(issuerAccount, {
|
|
183
|
+
fee: StellarSdk.BASE_FEE,
|
|
184
|
+
networkPassphrase: StellarSdk.Networks.TESTNET,
|
|
185
|
+
})
|
|
186
|
+
.addOperation(
|
|
187
|
+
StellarSdk.Operation.clawback({
|
|
188
|
+
asset: asset,
|
|
189
|
+
from: targetAccountId,
|
|
190
|
+
amount: "100",
|
|
191
|
+
})
|
|
192
|
+
)
|
|
193
|
+
.setTimeout(180)
|
|
194
|
+
.build();
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Trustlines
|
|
198
|
+
|
|
199
|
+
### Create Trustline
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
const changeTrustTx = new StellarSdk.TransactionBuilder(userAccount, {
|
|
203
|
+
fee: StellarSdk.BASE_FEE,
|
|
204
|
+
networkPassphrase: StellarSdk.Networks.TESTNET,
|
|
205
|
+
})
|
|
206
|
+
.addOperation(
|
|
207
|
+
StellarSdk.Operation.changeTrust({
|
|
208
|
+
asset: asset,
|
|
209
|
+
limit: "10000", // 0 to remove trustline
|
|
210
|
+
})
|
|
211
|
+
)
|
|
212
|
+
.setTimeout(180)
|
|
213
|
+
.build();
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Check Trustline Status
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
const account = await server.loadAccount(userPublicKey);
|
|
220
|
+
const trustline = account.balances.find(
|
|
221
|
+
(b) =>
|
|
222
|
+
b.asset_type !== "native" &&
|
|
223
|
+
b.asset_code === "USDC" &&
|
|
224
|
+
b.asset_issuer === usdcIssuer
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
if (trustline) {
|
|
228
|
+
console.log("Balance:", trustline.balance);
|
|
229
|
+
console.log("Limit:", trustline.limit);
|
|
230
|
+
console.log("Authorized:", trustline.is_authorized);
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Stellar Asset Contract (SAC)
|
|
235
|
+
|
|
236
|
+
SAC provides Soroban interface for Stellar Assets, enabling smart contract interactions.
|
|
237
|
+
|
|
238
|
+
### Deploy SAC for Existing Asset
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Get the SAC address for an asset
|
|
242
|
+
stellar contract asset deploy \
|
|
243
|
+
--asset USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN \
|
|
244
|
+
--source alice \
|
|
245
|
+
--network testnet
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### SAC Address Derivation
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import * as StellarSdk from "@stellar/stellar-sdk";
|
|
252
|
+
|
|
253
|
+
const asset = new StellarSdk.Asset("USDC", issuerPublicKey);
|
|
254
|
+
const contractId = asset.contractId(StellarSdk.Networks.TESTNET);
|
|
255
|
+
// Returns the deterministic SAC contract address
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Using SAC in Soroban Contracts
|
|
259
|
+
|
|
260
|
+
```rust
|
|
261
|
+
use soroban_sdk::{token::Client as TokenClient, Address, Env};
|
|
262
|
+
|
|
263
|
+
pub fn transfer_asset(
|
|
264
|
+
env: Env,
|
|
265
|
+
from: Address,
|
|
266
|
+
to: Address,
|
|
267
|
+
asset_contract: Address,
|
|
268
|
+
amount: i128,
|
|
269
|
+
) {
|
|
270
|
+
from.require_auth();
|
|
271
|
+
|
|
272
|
+
// Use standard token interface
|
|
273
|
+
let token = TokenClient::new(&env, &asset_contract);
|
|
274
|
+
token.transfer(&from, &to, &amount);
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### SAC vs Custom Token Interface
|
|
279
|
+
|
|
280
|
+
SAC implements the standard Soroban token interface:
|
|
281
|
+
- `balance(id: Address) -> i128`
|
|
282
|
+
- `transfer(from: Address, to: Address, amount: i128)`
|
|
283
|
+
- `approve(from: Address, spender: Address, amount: i128, expiration_ledger: u32)`
|
|
284
|
+
- `allowance(from: Address, spender: Address) -> i128`
|
|
285
|
+
- `decimals() -> u32`
|
|
286
|
+
- `name() -> String`
|
|
287
|
+
- `symbol() -> Symbol`
|
|
288
|
+
|
|
289
|
+
## When to Use What
|
|
290
|
+
|
|
291
|
+
### Use Stellar Assets When:
|
|
292
|
+
- Standard fungible token (currency, stablecoin)
|
|
293
|
+
- Need full ecosystem support (wallets, exchanges)
|
|
294
|
+
- Regulatory compliance features (freeze, clawback)
|
|
295
|
+
- Performance critical (classic operations are cheaper)
|
|
296
|
+
- DEX integration via order book
|
|
297
|
+
|
|
298
|
+
### Use Soroban Custom Tokens When:
|
|
299
|
+
- Complex transfer logic (royalties, fees, restrictions)
|
|
300
|
+
- Custom authorization schemes
|
|
301
|
+
- Non-standard token behaviors
|
|
302
|
+
- Integration with custom DeFi contracts
|
|
303
|
+
- NFTs or semi-fungible tokens
|
|
304
|
+
|
|
305
|
+
### Use SAC When:
|
|
306
|
+
- Need Stellar Asset in Soroban contract
|
|
307
|
+
- Building DeFi protocols with existing assets
|
|
308
|
+
- Bridge between classic and smart contract operations
|
|
309
|
+
|
|
310
|
+
## Querying Assets
|
|
311
|
+
|
|
312
|
+
### Get Account Balances
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
const account = await server.loadAccount(publicKey);
|
|
316
|
+
|
|
317
|
+
for (const balance of account.balances) {
|
|
318
|
+
if (balance.asset_type === "native") {
|
|
319
|
+
console.log("XLM:", balance.balance);
|
|
320
|
+
} else {
|
|
321
|
+
console.log(`${balance.asset_code}:`, balance.balance);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Find Assets
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
// Search for assets by code
|
|
330
|
+
const assets = await server
|
|
331
|
+
.assets()
|
|
332
|
+
.forCode("USDC")
|
|
333
|
+
.call();
|
|
334
|
+
|
|
335
|
+
// Get specific asset details
|
|
336
|
+
const assetDetails = await server
|
|
337
|
+
.assets()
|
|
338
|
+
.forCode("USDC")
|
|
339
|
+
.forIssuer(issuerPublicKey)
|
|
340
|
+
.call();
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Get Asset Statistics
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
const stats = await server
|
|
347
|
+
.assets()
|
|
348
|
+
.forCode("USDC")
|
|
349
|
+
.forIssuer(issuerPublicKey)
|
|
350
|
+
.call();
|
|
351
|
+
|
|
352
|
+
// stats includes:
|
|
353
|
+
// - amount: total issued
|
|
354
|
+
// - num_accounts: trustline count
|
|
355
|
+
// - flags: issuer flags
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## SEP Standards for Assets
|
|
359
|
+
|
|
360
|
+
### SEP-0001 (stellar.toml)
|
|
361
|
+
|
|
362
|
+
Publish asset metadata in your domain's `/.well-known/stellar.toml`:
|
|
363
|
+
|
|
364
|
+
```toml
|
|
365
|
+
[[CURRENCIES]]
|
|
366
|
+
code = "MYTOKEN"
|
|
367
|
+
issuer = "GABC..."
|
|
368
|
+
display_decimals = 2
|
|
369
|
+
name = "My Token"
|
|
370
|
+
desc = "A description of my token"
|
|
371
|
+
image = "https://example.com/token-logo.png"
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### SEP-0010 (Web Authentication)
|
|
375
|
+
|
|
376
|
+
Authenticate users with their Stellar accounts:
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
// Server generates challenge
|
|
380
|
+
// Client signs with wallet
|
|
381
|
+
// Server verifies signature
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### SEP-0024 (Hosted Deposit/Withdrawal)
|
|
385
|
+
|
|
386
|
+
For fiat on/off ramps:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// Interactive flow for deposits/withdrawals
|
|
390
|
+
// Anchor handles KYC and fiat transfer
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### SEP-0045 (Web Auth for Contract Accounts)
|
|
394
|
+
|
|
395
|
+
Extends SEP-10 to support Soroban contract accounts (`C...` addresses) for web authentication. Required for smart wallet / passkey-based anchor integrations. See [SEP-0045](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0045.md).
|
|
396
|
+
|
|
397
|
+
### SEP-0050 (Non-Fungible Tokens)
|
|
398
|
+
|
|
399
|
+
Standard contract interface for NFTs on Soroban. Reference implementations available in [OpenZeppelin Stellar Contracts](https://github.com/OpenZeppelin/stellar-contracts) with Base, Consecutive, and Enumerable variants. See [SEP-0050](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0050.md).
|
|
400
|
+
|
|
401
|
+
## Best Practices
|
|
402
|
+
|
|
403
|
+
### Asset Issuance
|
|
404
|
+
- Use separate issuing and distribution accounts
|
|
405
|
+
- Lock issuer after initial distribution for fixed supply
|
|
406
|
+
- Publish stellar.toml with asset metadata
|
|
407
|
+
- Consider multisig for issuer account
|
|
408
|
+
|
|
409
|
+
### Trustline Management
|
|
410
|
+
- Check trustline exists before sending payments
|
|
411
|
+
- Handle trustline creation in onboarding flow
|
|
412
|
+
- Respect trustline limits
|
|
413
|
+
- Monitor for frozen/deauthorized status
|
|
414
|
+
|
|
415
|
+
### Security
|
|
416
|
+
- Validate asset issuer, not just code
|
|
417
|
+
- Be cautious of assets with clawback enabled
|
|
418
|
+
- Verify stellar.toml from authoritative source
|
|
419
|
+
- Use well-known asset lists for common tokens
|