cspr402 0.4.7
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/LICENSE +21 -0
- package/README.md +173 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +108 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +207 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +400 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/onboard.d.ts +4 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +192 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/onboard.test.d.ts +2 -0
- package/dist/commands/onboard.test.d.ts.map +1 -0
- package/dist/commands/onboard.test.js +48 -0
- package/dist/commands/onboard.test.js.map +1 -0
- package/dist/commands/purchase.d.ts +2 -0
- package/dist/commands/purchase.d.ts.map +1 -0
- package/dist/commands/purchase.js +206 -0
- package/dist/commands/purchase.js.map +1 -0
- package/dist/commands/wallet.d.ts +2 -0
- package/dist/commands/wallet.d.ts.map +1 -0
- package/dist/commands/wallet.js +161 -0
- package/dist/commands/wallet.js.map +1 -0
- package/dist/config.d.ts +77 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +329 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +101 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +197 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +337 -0
- package/dist/mcp.js.map +1 -0
- package/dist/mpp.d.ts +57 -0
- package/dist/mpp.d.ts.map +1 -0
- package/dist/mpp.js +165 -0
- package/dist/mpp.js.map +1 -0
- package/dist/ows.d.ts +190 -0
- package/dist/ows.d.ts.map +1 -0
- package/dist/ows.js +565 -0
- package/dist/ows.js.map +1 -0
- package/dist/soroban.d.ts +92 -0
- package/dist/soroban.d.ts.map +1 -0
- package/dist/soroban.js +313 -0
- package/dist/soroban.js.map +1 -0
- package/dist/stellar.d.ts +53 -0
- package/dist/stellar.d.ts.map +1 -0
- package/dist/stellar.js +180 -0
- package/dist/stellar.js.map +1 -0
- package/dist/version-check.d.ts +5 -0
- package/dist/version-check.d.ts.map +1 -0
- package/dist/version-check.js +203 -0
- package/dist/version-check.js.map +1 -0
- package/package.json +80 -0
package/dist/ows.js
ADDED
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// OWS (Open Wallet Standard) wallet integration for cards402.
|
|
3
|
+
//
|
|
4
|
+
// Agents use an OWS wallet instead of a raw STELLAR_WALLET_SECRET:
|
|
5
|
+
// - Keys are encrypted at rest in the OWS vault file
|
|
6
|
+
// - BIP-44 derivation (m/44'/148'/0') for Stellar
|
|
7
|
+
// - Same wallet works across EVM, Solana, Stellar (multi-chain portability)
|
|
8
|
+
// - Supports passphrase protection and API key scoping
|
|
9
|
+
//
|
|
10
|
+
// Signing bridge: stellar-sdk computes the correct network-passphrase-prefixed
|
|
11
|
+
// hash; OWS ed25519-signs that hash; we attach the result as a DecoratedSignature.
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.payVCCOWS = void 0;
|
|
47
|
+
exports.createOWSWallet = createOWSWallet;
|
|
48
|
+
exports.importStellarKey = importStellarKey;
|
|
49
|
+
exports.getOWSPublicKey = getOWSPublicKey;
|
|
50
|
+
exports.getOWSBalance = getOWSBalance;
|
|
51
|
+
exports.onboardAgent = onboardAgent;
|
|
52
|
+
exports.checkSorobanTxLanded = checkSorobanTxLanded;
|
|
53
|
+
exports.addUsdcTrustlineOWS = addUsdcTrustlineOWS;
|
|
54
|
+
exports.payViaContractOWS = payViaContractOWS;
|
|
55
|
+
exports.purchaseCardOWS = purchaseCardOWS;
|
|
56
|
+
const stellar_ows_core_1 = require("@ctx.com/stellar-ows-core");
|
|
57
|
+
const stellar_sdk_1 = require("@stellar/stellar-sdk");
|
|
58
|
+
const errors_1 = require("./errors");
|
|
59
|
+
const soroban_1 = require("./soroban");
|
|
60
|
+
const USDC_ISSUER = 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN';
|
|
61
|
+
const STELLAR_CHAIN = 'stellar';
|
|
62
|
+
function assertSorobanPayment(payment) {
|
|
63
|
+
if (payment.type !== 'soroban_contract') {
|
|
64
|
+
throw new Error(`Expected soroban_contract payment instructions, got ${payment.type}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function withTimeout(promise, ms = 15000) {
|
|
68
|
+
return Promise.race([
|
|
69
|
+
promise,
|
|
70
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Horizon request timed out after ${ms}ms`)), ms)),
|
|
71
|
+
]);
|
|
72
|
+
}
|
|
73
|
+
// ── Wallet helpers ────────────────────────────────────────────────────────────
|
|
74
|
+
/** Extract the Stellar G-address from an OWS WalletInfo. */
|
|
75
|
+
function getStellarAddress(wallet) {
|
|
76
|
+
const account = wallet.accounts.find((a) => a.chainId.includes('stellar'));
|
|
77
|
+
if (!account)
|
|
78
|
+
throw new Error(`OWS wallet "${wallet.name}" has no Stellar account`);
|
|
79
|
+
return account.address;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Create an OWS wallet, or return the existing one if a wallet with this
|
|
83
|
+
* name already exists in the vault. Idempotent by design — calling it
|
|
84
|
+
* twice with the same name is safe and returns the same keys, so skill.md
|
|
85
|
+
* flows and agent retries don't duplicate state.
|
|
86
|
+
*
|
|
87
|
+
* Wallets are stored encrypted at `~/.ows/wallets/<name>.vault` by
|
|
88
|
+
* default. If the vault file is lost, the funds it controls become
|
|
89
|
+
* unreachable — cards402 never sees private keys and can't recover
|
|
90
|
+
* them. Agents running on ephemeral filesystems (Lambda, Cloud Run,
|
|
91
|
+
* scratch containers) should pass a `vaultPath` pointing at a
|
|
92
|
+
* persistent volume, or set the `OWS_VAULT_PATH` environment variable.
|
|
93
|
+
*/
|
|
94
|
+
function createOWSWallet(name, passphrase, vaultPath) {
|
|
95
|
+
// Fast path: existing wallet. Returns immediately if one is already in
|
|
96
|
+
// the vault under this name.
|
|
97
|
+
try {
|
|
98
|
+
const existing = (0, stellar_ows_core_1.getWallet)(name, vaultPath ?? null);
|
|
99
|
+
return { walletId: existing.id, publicKey: getStellarAddress(existing) };
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
/* not found — fall through to create */
|
|
103
|
+
}
|
|
104
|
+
const wallet = (0, stellar_ows_core_1.createWallet)(name, passphrase ?? null, undefined, vaultPath ?? null);
|
|
105
|
+
return { walletId: wallet.id, publicKey: getStellarAddress(wallet) };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Import an existing Stellar secret key (S...) into an OWS wallet.
|
|
109
|
+
* Useful for migrating from a raw STELLAR_WALLET_SECRET to OWS custody.
|
|
110
|
+
*/
|
|
111
|
+
function importStellarKey(name, stellarSecret, passphrase, vaultPath) {
|
|
112
|
+
const keypair = stellar_sdk_1.Keypair.fromSecret(stellarSecret);
|
|
113
|
+
const ed25519KeyHex = Buffer.from(keypair.rawSecretKey()).toString('hex');
|
|
114
|
+
const wallet = (0, stellar_ows_core_1.importWalletPrivateKey)(name, '', // secp256k1 key (EVM) — not used for Stellar
|
|
115
|
+
passphrase ?? null, vaultPath ?? null, STELLAR_CHAIN, null, // secp256K1Key — not used
|
|
116
|
+
ed25519KeyHex);
|
|
117
|
+
return { walletId: wallet.id, publicKey: getStellarAddress(wallet) };
|
|
118
|
+
}
|
|
119
|
+
/** Get the Stellar public key (G-address) for a named OWS wallet. */
|
|
120
|
+
function getOWSPublicKey(walletName, vaultPath) {
|
|
121
|
+
const wallet = (0, stellar_ows_core_1.getWallet)(walletName, vaultPath ?? null);
|
|
122
|
+
return getStellarAddress(wallet);
|
|
123
|
+
}
|
|
124
|
+
/** Check XLM and USDC balances for an OWS wallet. */
|
|
125
|
+
async function getOWSBalance(walletName, vaultPath, networkPassphrase) {
|
|
126
|
+
const publicKey = getOWSPublicKey(walletName, vaultPath);
|
|
127
|
+
const server = new stellar_sdk_1.Horizon.Server((0, soroban_1.getHorizonUrl)(networkPassphrase));
|
|
128
|
+
const account = await withTimeout(server.loadAccount(publicKey));
|
|
129
|
+
let xlm = '0', usdc = '0';
|
|
130
|
+
for (const b of account.balances) {
|
|
131
|
+
if (b.asset_type === 'native')
|
|
132
|
+
xlm = b.balance;
|
|
133
|
+
if (b.asset_type === 'credit_alphanum4' &&
|
|
134
|
+
b.asset_code === 'USDC' &&
|
|
135
|
+
b.asset_issuer === USDC_ISSUER)
|
|
136
|
+
usdc = b.balance;
|
|
137
|
+
}
|
|
138
|
+
return { xlm, usdc };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* One-shot agent setup: reports `initializing` to cards402, creates or
|
|
142
|
+
* fetches the OWS wallet, reports `awaiting_funding` with the wallet
|
|
143
|
+
* address, and returns the public key + current balance. Idempotent —
|
|
144
|
+
* safe to call on every agent startup.
|
|
145
|
+
*
|
|
146
|
+
* The backend broadcasts these transitions over the live SSE dashboard
|
|
147
|
+
* feed, so operators see the agent moving through states in real time.
|
|
148
|
+
*/
|
|
149
|
+
async function onboardAgent(opts) {
|
|
150
|
+
const { Cards402Client } = await Promise.resolve().then(() => __importStar(require('./client')));
|
|
151
|
+
const client = new Cards402Client({ apiKey: opts.apiKey, baseUrl: opts.baseUrl });
|
|
152
|
+
// 1. Signal "spinning up" before we touch the filesystem. Best-effort:
|
|
153
|
+
// reportStatus swallows errors so a backend hiccup can't block setup.
|
|
154
|
+
await client.reportStatus('initializing', { detail: 'creating wallet' });
|
|
155
|
+
// 2. Create or fetch the wallet. Idempotent via createOWSWallet's
|
|
156
|
+
// getWallet-first path.
|
|
157
|
+
const { publicKey } = createOWSWallet(opts.walletName, opts.passphrase, opts.vaultPath);
|
|
158
|
+
// 3. Fetch balance. On a fresh wallet this hits Horizon and may 404
|
|
159
|
+
// if the account isn't activated yet (< 1 XLM on-chain). Swallow
|
|
160
|
+
// that case and return 0/0; the dashboard will show "Awaiting
|
|
161
|
+
// deposit" and the next getOWSBalance call will see the funds.
|
|
162
|
+
let balance = { xlm: '0', usdc: '0' };
|
|
163
|
+
try {
|
|
164
|
+
balance = await getOWSBalance(opts.walletName, opts.vaultPath);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
/* unactivated account — normal on first run */
|
|
168
|
+
}
|
|
169
|
+
// 4. Report the wallet address so the dashboard can show it and
|
|
170
|
+
// start polling Horizon for the balance.
|
|
171
|
+
await client.reportStatus('awaiting_funding', {
|
|
172
|
+
wallet_public_key: publicKey,
|
|
173
|
+
detail: `xlm=${balance.xlm} usdc=${balance.usdc}`,
|
|
174
|
+
});
|
|
175
|
+
return { publicKey, balance };
|
|
176
|
+
}
|
|
177
|
+
function owsSignTx(tx, walletName, publicKey, passphrase, vaultPath) {
|
|
178
|
+
// The oceans404 Stellar fork's signTransaction expects the full transaction
|
|
179
|
+
// envelope XDR, NOT just the hash. It internally:
|
|
180
|
+
// 1. Parses the XDR envelope
|
|
181
|
+
// 2. Builds the network-passphrase-prefixed signature payload
|
|
182
|
+
// 3. Ed25519-signs the sha256 of that payload
|
|
183
|
+
// 4. Returns the raw 64-byte signature
|
|
184
|
+
const envelopeXdr = tx
|
|
185
|
+
.toEnvelope()
|
|
186
|
+
.toXDR('hex');
|
|
187
|
+
const { signature: sigHex } = (0, stellar_ows_core_1.signTransaction)(walletName, STELLAR_CHAIN, envelopeXdr, passphrase ?? null, null, vaultPath ?? null);
|
|
188
|
+
const pubKeyBytes = stellar_sdk_1.StrKey.decodeEd25519PublicKey(publicKey);
|
|
189
|
+
const hint = pubKeyBytes.slice(-4);
|
|
190
|
+
tx.signatures.push(new stellar_sdk_1.xdr.DecoratedSignature({
|
|
191
|
+
hint,
|
|
192
|
+
signature: Buffer.from(sigHex, 'hex'),
|
|
193
|
+
}));
|
|
194
|
+
return tx;
|
|
195
|
+
}
|
|
196
|
+
// ── Soroban tx landed-check ──────────────────────────────────────────────────
|
|
197
|
+
/**
|
|
198
|
+
* Check whether a Soroban tx hash has materialized on the Stellar
|
|
199
|
+
* ledger. Returns:
|
|
200
|
+
* - 'landed' — Horizon returned a successful tx record
|
|
201
|
+
* - 'dropped' — Horizon 404s and the caller has already exhausted
|
|
202
|
+
* the inclusion window client-side, so the tx is
|
|
203
|
+
* almost certainly gone
|
|
204
|
+
* - 'pending' — Horizon is down or the tx is still in the
|
|
205
|
+
* mempool; caller should wait rather than resubmit
|
|
206
|
+
*
|
|
207
|
+
* Used by purchaseCardOWS's resume branch to decide whether a
|
|
208
|
+
* dropped-pre-apply Soroban tx should be re-submitted or whether we
|
|
209
|
+
* should wait for a still-in-flight one to finalize.
|
|
210
|
+
*/
|
|
211
|
+
async function checkSorobanTxLanded(txHash, opts = {}) {
|
|
212
|
+
const horizonUrl = (0, soroban_1.getHorizonUrl)(opts.networkPassphrase);
|
|
213
|
+
try {
|
|
214
|
+
const res = await fetch(`${horizonUrl}/transactions/${txHash}`, {
|
|
215
|
+
signal: AbortSignal.timeout(10_000),
|
|
216
|
+
});
|
|
217
|
+
if (res.ok) {
|
|
218
|
+
const body = (await res.json());
|
|
219
|
+
return body.successful === false ? 'dropped' : 'landed';
|
|
220
|
+
}
|
|
221
|
+
if (res.status === 404) {
|
|
222
|
+
// Horizon doesn't know about this tx. The caller reached us
|
|
223
|
+
// only after an in-process submit already timed out past the
|
|
224
|
+
// 120s Soroban inclusion window, so a 404 now is as good a
|
|
225
|
+
// signal as we'll get that the tx was dropped pre-apply.
|
|
226
|
+
return 'dropped';
|
|
227
|
+
}
|
|
228
|
+
// Horizon returned an unexpected status — don't make a
|
|
229
|
+
// resubmit decision based on a flaky response.
|
|
230
|
+
return 'pending';
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// Network error hitting Horizon. Treat as pending — we'd
|
|
234
|
+
// rather wait than risk a double-pay on an unreliable signal.
|
|
235
|
+
return 'pending';
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Add a USDC trustline to the OWS wallet's Stellar account.
|
|
240
|
+
*
|
|
241
|
+
* Idempotent: if the trustline already exists, returns `null` without
|
|
242
|
+
* submitting a tx (Stellar accepts redundant `changeTrust` ops and
|
|
243
|
+
* silently no-ops them, but charges the base fee each time — so
|
|
244
|
+
* pre-checking saves ~0.00001 XLM per accidental re-run). Returns the
|
|
245
|
+
* new tx hash when a trustline is actually opened.
|
|
246
|
+
*/
|
|
247
|
+
async function addUsdcTrustlineOWS(opts) {
|
|
248
|
+
const { walletName, passphrase, vaultPath, networkPassphrase = stellar_sdk_1.Networks.PUBLIC } = opts;
|
|
249
|
+
const publicKey = getOWSPublicKey(walletName, vaultPath);
|
|
250
|
+
const horizonUrl = (0, soroban_1.getHorizonUrl)(networkPassphrase);
|
|
251
|
+
const server = new stellar_sdk_1.Horizon.Server(horizonUrl);
|
|
252
|
+
const account = await withTimeout(server.loadAccount(publicKey));
|
|
253
|
+
// Pre-check: already have a USDC trustline to the cards402-recognised
|
|
254
|
+
// issuer? Return null without spending a fee.
|
|
255
|
+
const balances = account.balances;
|
|
256
|
+
const hasTrustline = balances.some((b) => b.asset_type === 'credit_alphanum4' &&
|
|
257
|
+
b.asset_code === 'USDC' &&
|
|
258
|
+
b.asset_issuer === USDC_ISSUER);
|
|
259
|
+
if (hasTrustline)
|
|
260
|
+
return null;
|
|
261
|
+
const tx = new stellar_sdk_1.TransactionBuilder(account, { fee: stellar_sdk_1.BASE_FEE, networkPassphrase })
|
|
262
|
+
.addOperation(stellar_sdk_1.Operation.changeTrust({ asset: new stellar_sdk_1.Asset('USDC', USDC_ISSUER) }))
|
|
263
|
+
.setTimeout(300)
|
|
264
|
+
.build();
|
|
265
|
+
owsSignTx(tx, walletName, publicKey, passphrase, vaultPath);
|
|
266
|
+
const result = await server.submitTransaction(tx);
|
|
267
|
+
return result.hash;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Max total submit attempts made by payViaContractOWS before giving up
|
|
271
|
+
* and surfacing the last error to the caller. Retries are ONLY triggered
|
|
272
|
+
* by the `dropped: true` marker on the submit error — any other error
|
|
273
|
+
* (on-chain failure, validation, network, timeout without dropped
|
|
274
|
+
* signal) propagates immediately. 3 attempts is a comfortable upper
|
|
275
|
+
* bound: flaky mainnet RPC usually recovers within one retry, and
|
|
276
|
+
* retrying forever past a real incident just burns wallet fees.
|
|
277
|
+
*/
|
|
278
|
+
const PAY_VIA_CONTRACT_MAX_ATTEMPTS = 3;
|
|
279
|
+
/**
|
|
280
|
+
* Milliseconds to wait between retry attempts. Lets any in-flight
|
|
281
|
+
* original tx have one more ledger-close window to materialize before
|
|
282
|
+
* we build the retry. Stellar ledger close is ~5s, so 6s covers
|
|
283
|
+
* "one more ledger" plus a small buffer.
|
|
284
|
+
*/
|
|
285
|
+
const PAY_VIA_CONTRACT_RETRY_DELAY_MS = 6_000;
|
|
286
|
+
async function payViaContractOWS(opts, deps = {}) {
|
|
287
|
+
const { walletName, payment, paymentAsset = 'usdc', passphrase, vaultPath, networkPassphrase = stellar_sdk_1.Networks.PUBLIC, sorobanRpcUrl, } = opts;
|
|
288
|
+
// Resolve injectable deps — each defaults to the module-level
|
|
289
|
+
// real implementation, so production callers never notice the
|
|
290
|
+
// parameter exists. Tests inject stubs to exercise the retry
|
|
291
|
+
// state machine without touching real Soroban / OWS vault.
|
|
292
|
+
const buildTx = deps.buildContractPaymentTx ?? soroban_1.buildContractPaymentTx;
|
|
293
|
+
const submitTx = deps.submitSorobanTx ?? soroban_1.submitSorobanTx;
|
|
294
|
+
const signTx = deps.owsSignTx ?? owsSignTx;
|
|
295
|
+
const pubKeyOf = deps.getOWSPublicKey ?? getOWSPublicKey;
|
|
296
|
+
assertSorobanPayment(payment);
|
|
297
|
+
if (!stellar_sdk_1.StrKey.isValidContract(payment.contract_id)) {
|
|
298
|
+
throw new Error(`Invalid contract_id in order response: ${payment.contract_id}`);
|
|
299
|
+
}
|
|
300
|
+
const publicKey = pubKeyOf(walletName, vaultPath);
|
|
301
|
+
const { fn, amountDecimal } = (0, soroban_1.selectContractCall)(payment, paymentAsset);
|
|
302
|
+
const amountStroops = (0, soroban_1.decimalToStroops)(amountDecimal);
|
|
303
|
+
// Retry loop. First attempt uses the current on-chain sequence; any
|
|
304
|
+
// retry reuses the sequence from the previous attempt via the
|
|
305
|
+
// preservedSequence plumbing in buildContractPaymentTx. This gives
|
|
306
|
+
// us mutual exclusion with the prior (possibly still in-mempool)
|
|
307
|
+
// tx — at most one can land regardless of which the network picks.
|
|
308
|
+
//
|
|
309
|
+
// Retries only trigger on the `dropped: true` marker from
|
|
310
|
+
// submitSorobanTx, which is only set when Horizon explicitly reports
|
|
311
|
+
// 404 after the 120s client-side inclusion deadline. Any other error
|
|
312
|
+
// — on-chain failure, validation, submit-level error, txHash-
|
|
313
|
+
// attached-but-not-dropped — propagates out unchanged so
|
|
314
|
+
// purchaseCardOWS's caller-side handling stays correct.
|
|
315
|
+
let preservedSequence;
|
|
316
|
+
let suggestedFee;
|
|
317
|
+
let lastErr;
|
|
318
|
+
for (let attempt = 0; attempt < PAY_VIA_CONTRACT_MAX_ATTEMPTS; attempt++) {
|
|
319
|
+
const { tx, server } = await buildTx({
|
|
320
|
+
contractId: payment.contract_id,
|
|
321
|
+
fn,
|
|
322
|
+
fromPublicKey: publicKey,
|
|
323
|
+
amountStroops,
|
|
324
|
+
orderId: payment.order_id,
|
|
325
|
+
networkPassphrase,
|
|
326
|
+
rpcUrl: sorobanRpcUrl,
|
|
327
|
+
preservedSequence,
|
|
328
|
+
fee: suggestedFee,
|
|
329
|
+
});
|
|
330
|
+
// Capture the sequence this tx uses BEFORE signing / submitting.
|
|
331
|
+
// On retry we'll feed this back in as preservedSequence so the
|
|
332
|
+
// next build lands on the same number.
|
|
333
|
+
const thisSeq = tx.sequence;
|
|
334
|
+
signTx(tx, walletName, publicKey, passphrase, vaultPath);
|
|
335
|
+
try {
|
|
336
|
+
return await submitTx(tx, server, (0, soroban_1.getHorizonUrl)(networkPassphrase));
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
lastErr = err;
|
|
340
|
+
// Fee too low — retry with the network's required fee as floor.
|
|
341
|
+
// The tx was rejected pre-apply so no sequence was consumed;
|
|
342
|
+
// grab a fresh one on the next build (don't set preservedSequence).
|
|
343
|
+
if (err instanceof soroban_1.InsufficientFeeError) {
|
|
344
|
+
if (attempt >= PAY_VIA_CONTRACT_MAX_ATTEMPTS - 1)
|
|
345
|
+
throw err;
|
|
346
|
+
suggestedFee = err.requiredFee;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const dropped = err?.dropped === true;
|
|
350
|
+
// Not dropped → propagate. This covers on-chain failures
|
|
351
|
+
// (sequence already consumed, retry would fail tx_bad_seq),
|
|
352
|
+
// validation errors (same error on retry), and the
|
|
353
|
+
// "txHash-attached-but-Horizon-unreachable" case (where we
|
|
354
|
+
// DON'T know whether the tx is still pending — a retry with
|
|
355
|
+
// the same sequence might race, a retry with a fresh sequence
|
|
356
|
+
// might double-pay).
|
|
357
|
+
if (!dropped)
|
|
358
|
+
throw err;
|
|
359
|
+
// Dropped pre-apply. Reuse this sequence for the next build
|
|
360
|
+
// so the retry is mutually exclusive with the prior tx.
|
|
361
|
+
preservedSequence = thisSeq;
|
|
362
|
+
// No more attempts budgeted → surface the last error.
|
|
363
|
+
if (attempt >= PAY_VIA_CONTRACT_MAX_ATTEMPTS - 1)
|
|
364
|
+
throw err;
|
|
365
|
+
// Small delay before retry so any in-flight original gets one
|
|
366
|
+
// more ledger-close window to materialize. If it lands during
|
|
367
|
+
// the wait, our retry's matching sequence will be consumed and
|
|
368
|
+
// the retry submit will fail with tx_bad_seq — which is
|
|
369
|
+
// exactly the safety property we wanted.
|
|
370
|
+
await new Promise((r) => setTimeout(r, PAY_VIA_CONTRACT_RETRY_DELAY_MS));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// Unreachable — the loop either returns on success or throws on
|
|
374
|
+
// failure inside the catch. Fall-through exists only to satisfy the
|
|
375
|
+
// TS return-type checker.
|
|
376
|
+
throw lastErr ?? new Error('payViaContractOWS: retry loop exited without result');
|
|
377
|
+
}
|
|
378
|
+
// Back-compat aliases for the old exported names.
|
|
379
|
+
/** @deprecated Use `payViaContractOWS` — the old direct-Stellar path no longer matches the backend. */
|
|
380
|
+
exports.payVCCOWS = payViaContractOWS;
|
|
381
|
+
/**
|
|
382
|
+
* Full purchase flow using an OWS wallet: create order → pay the receiver
|
|
383
|
+
* contract on Stellar → wait for card. Any failure after the order exists
|
|
384
|
+
* is wrapped as a ResumableError so the caller can retry via `--resume`
|
|
385
|
+
* without minting a new order.
|
|
386
|
+
*
|
|
387
|
+
* Soroban RPC backpressure is tolerated: if submitSorobanTx throws with a
|
|
388
|
+
* txHash attached (deadline reached but tx may still land), we proceed to
|
|
389
|
+
* waitForCard — the cards402 backend watcher is the source of truth and
|
|
390
|
+
* will credit the order when the tx finalizes.
|
|
391
|
+
*/
|
|
392
|
+
async function purchaseCardOWS(opts) {
|
|
393
|
+
const { Cards402Client } = await Promise.resolve().then(() => __importStar(require('./client')));
|
|
394
|
+
const client = new Cards402Client({ apiKey: opts.apiKey, baseUrl: opts.baseUrl });
|
|
395
|
+
const paymentAsset = opts.paymentAsset ?? 'usdc';
|
|
396
|
+
let orderId;
|
|
397
|
+
let payment;
|
|
398
|
+
let skipPayment = false;
|
|
399
|
+
if (opts.resume) {
|
|
400
|
+
let priorTxHash;
|
|
401
|
+
let priorPhase;
|
|
402
|
+
if (typeof opts.resume === 'string') {
|
|
403
|
+
orderId = opts.resume;
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
orderId = opts.resume.orderId;
|
|
407
|
+
payment = opts.resume.payment;
|
|
408
|
+
priorTxHash = opts.resume.txHash;
|
|
409
|
+
priorPhase = opts.resume.phase;
|
|
410
|
+
}
|
|
411
|
+
// Check where the order is — if the payment already landed (or is
|
|
412
|
+
// landing), we can skip straight to waitForCard.
|
|
413
|
+
const status = await client.getOrder(orderId);
|
|
414
|
+
if (status.phase === 'ready' && status.card) {
|
|
415
|
+
return { ...status.card, order_id: orderId };
|
|
416
|
+
}
|
|
417
|
+
if (status.phase === 'failed' ||
|
|
418
|
+
status.phase === 'refunded' ||
|
|
419
|
+
status.phase === 'rejected' ||
|
|
420
|
+
status.phase === 'expired') {
|
|
421
|
+
throw new errors_1.OrderFailedError(orderId, status.error ?? status.phase, status.refund);
|
|
422
|
+
}
|
|
423
|
+
if (status.phase !== 'awaiting_payment') {
|
|
424
|
+
// processing / awaiting_approval — backend is working, just wait.
|
|
425
|
+
skipPayment = true;
|
|
426
|
+
}
|
|
427
|
+
else if (payment) {
|
|
428
|
+
// Caller handed in a fresh payment object — resubmit.
|
|
429
|
+
// skipPayment stays false; fall through.
|
|
430
|
+
}
|
|
431
|
+
else if (priorTxHash && priorPhase === 'unpaid') {
|
|
432
|
+
// F1-resume fix: we have a captured tx hash from a prior
|
|
433
|
+
// ResumableError where the client never saw the tx land. Check
|
|
434
|
+
// Horizon ONE MORE TIME to see if it's materialized since the
|
|
435
|
+
// error fired — Soroban RPCs occasionally report NOT_FOUND
|
|
436
|
+
// briefly past the 120s inclusion window before the tx shows
|
|
437
|
+
// up. If Horizon still doesn't know about it, call it dropped
|
|
438
|
+
// and rebuild the payment from the order's persisted
|
|
439
|
+
// instructions (the backend returns `payment` on the order
|
|
440
|
+
// response for pending_payment orders) so we can resubmit
|
|
441
|
+
// instead of defaulting to a 5-minute waitForCard hang.
|
|
442
|
+
const landed = await checkSorobanTxLanded(priorTxHash);
|
|
443
|
+
if (landed === 'landed') {
|
|
444
|
+
// Tx is on the ledger — backend will see the Soroban event
|
|
445
|
+
// any second. Wait.
|
|
446
|
+
skipPayment = true;
|
|
447
|
+
}
|
|
448
|
+
else if (landed === 'dropped' && status.payment) {
|
|
449
|
+
// Dropped pre-apply. Rebuild payment from the backend's
|
|
450
|
+
// view of the order (which includes the original Soroban
|
|
451
|
+
// contract invocation parameters) and re-submit.
|
|
452
|
+
payment = status.payment;
|
|
453
|
+
// skipPayment stays false — fall through to the submit path.
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
// Still pending, or we couldn't tell. Be conservative and
|
|
457
|
+
// wait — resubmitting a tx that's actually still in the
|
|
458
|
+
// mempool would double-pay if both eventually land.
|
|
459
|
+
skipPayment = true;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
// No prior tx context (either bare-string resume, or the
|
|
464
|
+
// saved state had no txHash). Conservative wait.
|
|
465
|
+
skipPayment = true;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
const order = await client.createOrder({ amount_usdc: opts.amountUsdc });
|
|
470
|
+
orderId = order.order_id;
|
|
471
|
+
payment = order.payment;
|
|
472
|
+
}
|
|
473
|
+
if (!skipPayment) {
|
|
474
|
+
if (!payment) {
|
|
475
|
+
// Unreachable: the resume branch sets skipPayment when payment is
|
|
476
|
+
// missing, and the create branch always sets payment.
|
|
477
|
+
throw new errors_1.ResumableError(orderId, 'internal: payment instructions missing for an unpaid order', 'unpaid');
|
|
478
|
+
}
|
|
479
|
+
// USDC payments need a trustline on the wallet's Stellar account. If the
|
|
480
|
+
// agent is paying in USDC and never added one, add it now so the
|
|
481
|
+
// purchase doesn't silently fail on the payment step.
|
|
482
|
+
if (paymentAsset === 'usdc') {
|
|
483
|
+
try {
|
|
484
|
+
const bal = await getOWSBalance(opts.walletName, opts.vaultPath);
|
|
485
|
+
if (bal.usdc === '0') {
|
|
486
|
+
const publicKey = getOWSPublicKey(opts.walletName, opts.vaultPath);
|
|
487
|
+
const server = new stellar_sdk_1.Horizon.Server((0, soroban_1.getHorizonUrl)(opts.networkPassphrase));
|
|
488
|
+
const account = await withTimeout(server.loadAccount(publicKey));
|
|
489
|
+
const hasTrustline = account.balances.some((b) => b.asset_type === 'credit_alphanum4' &&
|
|
490
|
+
b.asset_code === 'USDC' &&
|
|
491
|
+
b.asset_issuer === USDC_ISSUER);
|
|
492
|
+
if (!hasTrustline) {
|
|
493
|
+
await addUsdcTrustlineOWS({
|
|
494
|
+
walletName: opts.walletName,
|
|
495
|
+
passphrase: opts.passphrase,
|
|
496
|
+
vaultPath: opts.vaultPath,
|
|
497
|
+
networkPassphrase: opts.networkPassphrase,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
catch (err) {
|
|
503
|
+
throw new errors_1.ResumableError(orderId, `failed to ensure USDC trustline: ${err instanceof Error ? err.message : String(err)}. The wallet needs at least 2 XLM (1 for the account reserve, 1 for the trustline)`, 'unpaid', undefined, err);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
try {
|
|
507
|
+
await payViaContractOWS({
|
|
508
|
+
walletName: opts.walletName,
|
|
509
|
+
payment,
|
|
510
|
+
paymentAsset,
|
|
511
|
+
passphrase: opts.passphrase,
|
|
512
|
+
vaultPath: opts.vaultPath,
|
|
513
|
+
networkPassphrase: opts.networkPassphrase,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
catch (err) {
|
|
517
|
+
// submitSorobanTx attaches `txHash` to its error when the envelope
|
|
518
|
+
// has been accepted onto the network but we gave up waiting for
|
|
519
|
+
// finalization. The DISPOSITION of that hash matters:
|
|
520
|
+
//
|
|
521
|
+
// - dropped: true → payViaContractOWS exhausted its retry
|
|
522
|
+
// budget on a provably-dropped tx. There
|
|
523
|
+
// is no in-mempool tx to wait for, and
|
|
524
|
+
// waitForCard would hang the full timeout.
|
|
525
|
+
// Surface as ResumableError('unpaid') so
|
|
526
|
+
// the CLI can save the saved state and
|
|
527
|
+
// the next --resume run can try again.
|
|
528
|
+
//
|
|
529
|
+
// - dropped: false / — envelope may still land (e.g. Horizon
|
|
530
|
+
// absent unreachable, couldn't confirm either way).
|
|
531
|
+
// Fall through to waitForCard so the
|
|
532
|
+
// backend watcher has a chance to credit
|
|
533
|
+
// the order if the tx finalizes.
|
|
534
|
+
//
|
|
535
|
+
// - no txHash → submit never reached a known hash (pre-
|
|
536
|
+
// simulation failure, trustline add error,
|
|
537
|
+
// etc.). Resumable as 'unpaid'.
|
|
538
|
+
const errWithHash = err;
|
|
539
|
+
const hasHash = typeof errWithHash.txHash === 'string';
|
|
540
|
+
const dropped = errWithHash.dropped === true;
|
|
541
|
+
if (!hasHash || dropped) {
|
|
542
|
+
throw new errors_1.ResumableError(orderId, err instanceof Error ? err.message : String(err), 'unpaid', errWithHash.txHash, err);
|
|
543
|
+
}
|
|
544
|
+
// hasHash && !dropped — envelope may still land. Fall through.
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
try {
|
|
548
|
+
const card = await client.waitForCard(orderId, opts.waitForCardOpts);
|
|
549
|
+
return { ...card, order_id: orderId };
|
|
550
|
+
}
|
|
551
|
+
catch (err) {
|
|
552
|
+
// OrderFailedError is terminal — propagate unchanged so the CLI
|
|
553
|
+
// surfaces the real reason instead of a misleading resume hint.
|
|
554
|
+
if (err instanceof errors_1.OrderFailedError)
|
|
555
|
+
throw err;
|
|
556
|
+
// Auth / budget / validation errors from the client are also terminal.
|
|
557
|
+
if (err instanceof errors_1.Cards402Error && err.code !== 'wait_timeout')
|
|
558
|
+
throw err;
|
|
559
|
+
// Everything else (network blip, SSE disconnect, wait_timeout) — wrap
|
|
560
|
+
// as resumable. The order is paid at this point; resuming will just
|
|
561
|
+
// re-attach to the stream.
|
|
562
|
+
throw new errors_1.ResumableError(orderId, err instanceof Error ? err.message : String(err), 'paid', undefined, err);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
//# sourceMappingURL=ows.js.map
|
package/dist/ows.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ows.js","sourceRoot":"","sources":["../src/ows.ts"],"names":[],"mappings":"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"}
|