spare-sdk 0.1.0 → 0.1.2
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 +1 -1
- package/README.md +15 -3
- package/dist/add-donation.js +12 -3
- package/dist/add-donation.js.map +1 -1
- package/dist/donate-after.d.ts +5 -1
- package/dist/donate-after.js +12 -3
- package/dist/donate-after.js.map +1 -1
- package/dist/horizon.d.ts +11 -3
- package/dist/horizon.js +14 -6
- package/dist/horizon.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/network.d.ts +11 -0
- package/dist/network.js +20 -0
- package/dist/network.js.map +1 -0
- package/dist/ports.d.ts +3 -0
- package/dist/spend.d.ts +3 -2
- package/dist/spend.js +4 -3
- package/dist/spend.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/package.json +1 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -11,12 +11,15 @@ pnpm add spare-sdk @stellar/stellar-sdk
|
|
|
11
11
|
```ts
|
|
12
12
|
import { addDonation, HorizonAccountPort } from "spare-sdk";
|
|
13
13
|
|
|
14
|
+
const network = "testnet"; // "mainnet" in production
|
|
15
|
+
|
|
14
16
|
const result = await addDonation(unsignedTx, {
|
|
15
17
|
foundation: { account: "G...", domain: "foundation.org" }, // must be listed in its stellar.toml
|
|
16
18
|
amount: "0.50", // or: roundUp: true (only when the purchase is USDC)
|
|
17
19
|
appId: "my-app", // <= 22 ASCII bytes, memo becomes "spare:my-app"
|
|
18
20
|
maxAmount: "5", // your cap per donation
|
|
19
|
-
accounts: new HorizonAccountPort(
|
|
21
|
+
accounts: new HorizonAccountPort({ network }),
|
|
22
|
+
network,
|
|
20
23
|
});
|
|
21
24
|
|
|
22
25
|
switch (result.status) {
|
|
@@ -37,11 +40,20 @@ Only when the whole tx is a Circle-USDC purchase (payments, `pathPaymentStrictSe
|
|
|
37
40
|
- Already whole (e.g. 5.00): `round-up-already-whole`.
|
|
38
41
|
- `pathPaymentStrictReceive`, XLM or other-asset ops, or unmodelled ops in the same tx: `round-up-needs-usdc-purchase` (the real spend is unknown up front, so Spare never rounds `sendMax`).
|
|
39
42
|
|
|
43
|
+
### Networks
|
|
44
|
+
|
|
45
|
+
`network` is `"mainnet"` (default) or `"testnet"` and selects the only accepted Circle USDC issuer:
|
|
46
|
+
|
|
47
|
+
- mainnet: `GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN`
|
|
48
|
+
- testnet: `GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5`
|
|
49
|
+
|
|
50
|
+
A tx built for the other network is `not-offered` with `network-mismatch`. Pass the same `network` to `new HorizonAccountPort({ network })` so balances are read from the right Horizon. (`NETWORKS` exports both configs.)
|
|
51
|
+
|
|
40
52
|
### Reason codes
|
|
41
53
|
|
|
42
54
|
`passthrough` (tx untouched): `fee-bump`, `already-signed`, `soroban`, `multiple-sources`, `multisig` (the master key alone cannot meet the tx's threshold: medium, or high with `setOptions`/`accountMerge`), `extra-signers` (CAP-21 `extraSigners` precondition).
|
|
43
55
|
|
|
44
|
-
`not-offered`: `invalid-options` (incl. malformed `baseFee`), `invalid-app-id`, `invalid-amount`, `invalid-foundation`, `amount-over-cap`, `round-up-needs-usdc-purchase`, `round-up-already-whole`, `foundation-not-verified`, `foundation-trustline-missing`, `foundation-trustline-unauthorized`, `foundation-trustline-full` (no room under the trustline limit), `user-trustline-missing`, `user-trustline-unauthorized`, `unsupported-operation` (the tx has ops that can spend funds in ways Spare does not model, e.g. `manageBuyOffer`, `createClaimableBalance`, `liquidityPoolDeposit`, `accountMerge`), `insufficient-balance` (USDC, or XLM for the fee plus any XLM the tx sends), `account-lookup-failed`, `main-tx-not-successful`, and, from `donateAfter` only, `multisig`.
|
|
56
|
+
`not-offered`: `invalid-options` (incl. malformed `baseFee`), `invalid-app-id`, `invalid-amount`, `invalid-foundation`, `amount-over-cap`, `round-up-needs-usdc-purchase`, `round-up-already-whole`, `foundation-not-verified`, `foundation-trustline-missing`, `foundation-trustline-unauthorized`, `foundation-trustline-full` (no room under the trustline limit), `user-trustline-missing`, `user-trustline-unauthorized`, `unsupported-operation` (the tx has ops that can spend funds in ways Spare does not model, e.g. `manageBuyOffer`, `createClaimableBalance`, `liquidityPoolDeposit`, `accountMerge`), `insufficient-balance` (USDC, or XLM for the fee plus any XLM the tx sends), `network-mismatch` (the tx passphrase is not the one of `network`), `account-lookup-failed`, `main-tx-not-successful`, and, from `donateAfter` only, `multisig`.
|
|
45
57
|
|
|
46
58
|
### Memo and SEP-29
|
|
47
59
|
|
|
@@ -61,7 +73,7 @@ import { donateAfter } from "spare-sdk";
|
|
|
61
73
|
const follow = await donateAfter(
|
|
62
74
|
{ successful: true, sourceAccount: userAccount, hash },
|
|
63
75
|
{ foundation, amount: "0.50", appId: "my-app", maxAmount: "5",
|
|
64
|
-
accounts,
|
|
76
|
+
accounts, network },
|
|
65
77
|
);
|
|
66
78
|
if (follow.status === "offered") { /* confirm, then sign follow.transaction */ }
|
|
67
79
|
```
|
package/dist/add-donation.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Asset, FeeBumpTransaction, Memo, Operation, TransactionBuilder, } from "@stellar/stellar-sdk";
|
|
2
2
|
import { formatStroops, parseUsdc, roundUpToWholeDollar, toStroops } from "./amount.js";
|
|
3
3
|
import { memoFor } from "./app-id.js";
|
|
4
|
-
import { USDC_CODE
|
|
4
|
+
import { USDC_CODE } from "./constants.js";
|
|
5
5
|
import { checkEligibility } from "./eligibility.js";
|
|
6
6
|
import { perOpFee } from "./fee.js";
|
|
7
|
+
import { isNetwork, NETWORKS } from "./network.js";
|
|
7
8
|
import { canSignAlone, requiredThreshold } from "./signing.js";
|
|
8
9
|
import { analyzeSpend } from "./spend.js";
|
|
9
10
|
const SOROBAN_OPS = new Set(["invokeHostFunction", "extendFootprintTtl", "restoreFootprint"]);
|
|
@@ -61,11 +62,19 @@ export async function addDonation(tx, opts) {
|
|
|
61
62
|
const no = (reason) => ({ status: "not-offered", reason, transaction: t });
|
|
62
63
|
if ((opts.amount === undefined) === (opts.roundUp !== true))
|
|
63
64
|
return no("invalid-options");
|
|
65
|
+
const networkName = opts.network ?? "mainnet";
|
|
66
|
+
if (!isNetwork(networkName))
|
|
67
|
+
return no("invalid-options");
|
|
68
|
+
const network = NETWORKS[networkName];
|
|
69
|
+
if (t.networkPassphrase !== network.passphrase)
|
|
70
|
+
return no("network-mismatch");
|
|
71
|
+
if (opts.accounts.network !== undefined && opts.accounts.network !== networkName)
|
|
72
|
+
return no("network-mismatch");
|
|
64
73
|
const feeFallback = (BigInt(t.fee) + BigInt(t.operations.length) - 1n) / BigInt(t.operations.length);
|
|
65
74
|
const perOp = perOpFee(opts.baseFee, feeFallback);
|
|
66
75
|
if (perOp === null)
|
|
67
76
|
return no("invalid-options");
|
|
68
|
-
const spend = analyzeSpend(t.operations);
|
|
77
|
+
const spend = analyzeSpend(t.operations, network.usdcIssuer);
|
|
69
78
|
if (spend.unsupported)
|
|
70
79
|
return no("unsupported-operation");
|
|
71
80
|
let amount;
|
|
@@ -118,7 +127,7 @@ export async function addDonation(tx, opts) {
|
|
|
118
127
|
});
|
|
119
128
|
builder.addOperation(Operation.payment({
|
|
120
129
|
destination: opts.foundation.account,
|
|
121
|
-
asset: new Asset(USDC_CODE,
|
|
130
|
+
asset: new Asset(USDC_CODE, network.usdcIssuer),
|
|
122
131
|
amount: formatStroops(amount),
|
|
123
132
|
}));
|
|
124
133
|
const out = builder.build();
|
package/dist/add-donation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add-donation.js","sourceRoot":"","sources":["../src/add-donation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,EAAe,kBAAkB,GAC5E,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"add-donation.js","sourceRoot":"","sources":["../src/add-donation.ts"],"names":[],"mappings":"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"}
|
package/dist/donate-after.d.ts
CHANGED
|
@@ -10,7 +10,11 @@ export interface MainTxResult {
|
|
|
10
10
|
export type DonateAfterOptions = CommonOptions & {
|
|
11
11
|
/** Fixed amount in USDC. Round-up is not available on this path. */
|
|
12
12
|
amount: string;
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @deprecated Derived from `network`. If given, it must equal that network's passphrase,
|
|
15
|
+
* else `not-offered` / `network-mismatch`.
|
|
16
|
+
*/
|
|
17
|
+
networkPassphrase?: string | undefined;
|
|
14
18
|
/** Seconds the follow-up tx stays valid. Default 300. */
|
|
15
19
|
timeoutSeconds?: number;
|
|
16
20
|
};
|
package/dist/donate-after.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Account, Asset, Memo, Operation, TransactionBuilder, } from "@stellar/stellar-sdk";
|
|
2
2
|
import { formatStroops, parseUsdc, toStroops } from "./amount.js";
|
|
3
3
|
import { memoFor } from "./app-id.js";
|
|
4
|
-
import { USDC_CODE
|
|
4
|
+
import { USDC_CODE } from "./constants.js";
|
|
5
5
|
import { checkEligibility } from "./eligibility.js";
|
|
6
6
|
import { perOpFee } from "./fee.js";
|
|
7
|
+
import { isNetwork, NETWORKS } from "./network.js";
|
|
7
8
|
import { canSignAlone } from "./signing.js";
|
|
8
9
|
/**
|
|
9
10
|
* Soroban path: an InvokeHostFunction tx holds a single operation, so the donation is a separate
|
|
@@ -14,6 +15,14 @@ export async function donateAfter(result, opts) {
|
|
|
14
15
|
const no = (reason) => ({ status: "not-offered", reason });
|
|
15
16
|
if (!result.successful)
|
|
16
17
|
return no("main-tx-not-successful");
|
|
18
|
+
const networkName = opts.network ?? "mainnet";
|
|
19
|
+
if (!isNetwork(networkName))
|
|
20
|
+
return no("invalid-options");
|
|
21
|
+
const network = NETWORKS[networkName];
|
|
22
|
+
if (opts.networkPassphrase !== undefined && opts.networkPassphrase !== network.passphrase)
|
|
23
|
+
return no("network-mismatch");
|
|
24
|
+
if (opts.accounts.network !== undefined && opts.accounts.network !== networkName)
|
|
25
|
+
return no("network-mismatch");
|
|
17
26
|
const amount = parseUsdc(opts.amount);
|
|
18
27
|
if (amount === null)
|
|
19
28
|
return no("invalid-amount");
|
|
@@ -49,12 +58,12 @@ export async function donateAfter(result, opts) {
|
|
|
49
58
|
return no(reason);
|
|
50
59
|
const tx = new TransactionBuilder(new Account(result.sourceAccount, user.sequence), {
|
|
51
60
|
fee: baseFee.toString(),
|
|
52
|
-
networkPassphrase:
|
|
61
|
+
networkPassphrase: network.passphrase,
|
|
53
62
|
memo: Memo.text(memoFor(opts.appId)),
|
|
54
63
|
})
|
|
55
64
|
.addOperation(Operation.payment({
|
|
56
65
|
destination: opts.foundation.account,
|
|
57
|
-
asset: new Asset(USDC_CODE,
|
|
66
|
+
asset: new Asset(USDC_CODE, network.usdcIssuer),
|
|
58
67
|
amount: formatStroops(amount),
|
|
59
68
|
}))
|
|
60
69
|
.setTimeout(opts.timeoutSeconds ?? 300)
|
package/dist/donate-after.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"donate-after.js","sourceRoot":"","sources":["../src/donate-after.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAe,kBAAkB,GACjE,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"donate-after.js","sourceRoot":"","sources":["../src/donate-after.ts"],"names":[],"mappings":"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"}
|
package/dist/horizon.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Horizon } from "@stellar/stellar-sdk";
|
|
2
|
+
import { type Network } from "./network.js";
|
|
2
3
|
import type { AccountPort, AccountSnapshot } from "./ports.js";
|
|
3
4
|
/** The subset of Horizon's account record that Spare reads. */
|
|
4
5
|
export interface HorizonAccountRecord {
|
|
@@ -29,10 +30,17 @@ export interface HorizonAccountRecord {
|
|
|
29
30
|
is_authorized?: boolean;
|
|
30
31
|
}[];
|
|
31
32
|
}
|
|
32
|
-
export declare function toAccountSnapshot(r: HorizonAccountRecord): AccountSnapshot;
|
|
33
|
-
|
|
33
|
+
export declare function toAccountSnapshot(r: HorizonAccountRecord, issuer?: string): AccountSnapshot;
|
|
34
|
+
export interface HorizonAccountPortOptions {
|
|
35
|
+
/** Default "mainnet". Picks the Horizon URL (unless `horizon` is set) and the USDC issuer. */
|
|
36
|
+
network?: Network;
|
|
37
|
+
/** Horizon URL or server; overrides the network's default URL. */
|
|
38
|
+
horizon?: string | Horizon.Server;
|
|
39
|
+
}
|
|
40
|
+
/** AccountPort backed by a Horizon server. A string or Server argument means mainnet. */
|
|
34
41
|
export declare class HorizonAccountPort implements AccountPort {
|
|
42
|
+
readonly network: Network;
|
|
35
43
|
private readonly server;
|
|
36
|
-
constructor(
|
|
44
|
+
constructor(arg?: string | Horizon.Server | HorizonAccountPortOptions);
|
|
37
45
|
loadAccount(accountId: string): Promise<AccountSnapshot | null>;
|
|
38
46
|
}
|
package/dist/horizon.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Horizon } from "@stellar/stellar-sdk";
|
|
2
2
|
import { toStroops } from "./amount.js";
|
|
3
3
|
import { USDC_CODE, USDC_ISSUER } from "./constants.js";
|
|
4
|
+
import { isNetwork, NETWORKS } from "./network.js";
|
|
4
5
|
const RESERVE_UNIT = 5000000n; // 0.5 XLM
|
|
5
6
|
const net = (balance, liabilities) => (balance > liabilities ? balance - liabilities : 0n);
|
|
6
|
-
export function toAccountSnapshot(r) {
|
|
7
|
+
export function toAccountSnapshot(r, issuer = USDC_ISSUER) {
|
|
7
8
|
const native = r.balances.find((b) => b.asset_type === "native");
|
|
8
9
|
const reserve = BigInt(2 + r.subentry_count + r.num_sponsoring - r.num_sponsored) * RESERVE_UNIT;
|
|
9
10
|
const nativeNet = net(toStroops(native?.balance ?? "0") ?? 0n, (toStroops(native?.selling_liabilities ?? "0") ?? 0n) + reserve);
|
|
10
|
-
const line = r.balances.find((b) => b.asset_code === USDC_CODE && b.asset_issuer ===
|
|
11
|
+
const line = r.balances.find((b) => b.asset_code === USDC_CODE && b.asset_issuer === issuer && b.asset_type !== "native");
|
|
11
12
|
const masterWeight = r.signers.find((s) => s.key === r.account_id)?.weight ?? 0;
|
|
12
13
|
// SEP-29: data entry config.memo_required = "1" (base64 "MQ==").
|
|
13
14
|
const memoRequired = r.data_attr?.["config.memo_required"] === "MQ==";
|
|
@@ -31,16 +32,23 @@ export function toAccountSnapshot(r) {
|
|
|
31
32
|
memoRequired,
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
|
-
/** AccountPort backed by a Horizon server. */
|
|
35
|
+
/** AccountPort backed by a Horizon server. A string or Server argument means mainnet. */
|
|
35
36
|
export class HorizonAccountPort {
|
|
37
|
+
network;
|
|
36
38
|
server;
|
|
37
|
-
constructor(
|
|
38
|
-
|
|
39
|
+
constructor(arg = {}) {
|
|
40
|
+
const o = typeof arg === "string" || arg instanceof Horizon.Server ? { horizon: arg } : arg;
|
|
41
|
+
const network = o.network ?? "mainnet";
|
|
42
|
+
if (!isNetwork(network))
|
|
43
|
+
throw new Error(`unknown network: ${String(network)}`);
|
|
44
|
+
this.network = network;
|
|
45
|
+
const h = o.horizon ?? NETWORKS[network].horizonUrl;
|
|
46
|
+
this.server = typeof h === "string" ? new Horizon.Server(h) : h;
|
|
39
47
|
}
|
|
40
48
|
async loadAccount(accountId) {
|
|
41
49
|
try {
|
|
42
50
|
const rec = await this.server.accounts().accountId(accountId).call();
|
|
43
|
-
return toAccountSnapshot(rec);
|
|
51
|
+
return toAccountSnapshot(rec, NETWORKS[this.network].usdcIssuer);
|
|
44
52
|
}
|
|
45
53
|
catch (e) {
|
|
46
54
|
if (e.response?.status === 404)
|
package/dist/horizon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"horizon.js","sourceRoot":"","sources":["../src/horizon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"horizon.js","sourceRoot":"","sources":["../src/horizon.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export { addDonation, type AddDonationOptions } from "./add-donation.js";
|
|
2
2
|
export { donateAfter, type DonateAfterOptions, type DonateAfterResult, type MainTxResult } from "./donate-after.js";
|
|
3
3
|
export { verifyFoundation, listVerifiedFoundations } from "./stellar-toml.js";
|
|
4
|
-
export { HorizonAccountPort, toAccountSnapshot, type HorizonAccountRecord } from "./horizon.js";
|
|
4
|
+
export { HorizonAccountPort, toAccountSnapshot, type HorizonAccountRecord, type HorizonAccountPortOptions } from "./horizon.js";
|
|
5
5
|
export { parseUsdc, formatStroops, roundUpToWholeDollar } from "./amount.js";
|
|
6
6
|
export { isValidAppId, memoFor } from "./app-id.js";
|
|
7
7
|
export { USDC_ISSUER, USDC_CODE } from "./constants.js";
|
|
8
|
+
export { NETWORKS, type Network, type NetworkConfig } from "./network.js";
|
|
8
9
|
export type { AccountPort, AccountSnapshot, FetchLike, Foundation } from "./ports.js";
|
|
9
10
|
export type { CommonOptions, DonationInfo, DonationResult, NotOfferedReason, PassthroughReason, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -5,4 +5,5 @@ export { HorizonAccountPort, toAccountSnapshot } from "./horizon.js";
|
|
|
5
5
|
export { parseUsdc, formatStroops, roundUpToWholeDollar } from "./amount.js";
|
|
6
6
|
export { isValidAppId, memoFor } from "./app-id.js";
|
|
7
7
|
export { USDC_ISSUER, USDC_CODE } from "./constants.js";
|
|
8
|
+
export { NETWORKS } from "./network.js";
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAsE,MAAM,mBAAmB,CAAC;AACpH,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAsE,MAAM,mBAAmB,CAAC;AACpH,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAA6D,MAAM,cAAc,CAAC;AAChI,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAoC,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type Network = "mainnet" | "testnet";
|
|
2
|
+
export interface NetworkConfig {
|
|
3
|
+
network: Network;
|
|
4
|
+
passphrase: string;
|
|
5
|
+
/** The one USDC issuer Spare accepts on this network. There is no override. */
|
|
6
|
+
usdcIssuer: string;
|
|
7
|
+
horizonUrl: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const NETWORKS: Readonly<Record<Network, NetworkConfig>>;
|
|
10
|
+
/** Runtime guard: the type says Network, but JS callers can pass anything. */
|
|
11
|
+
export declare const isNetwork: (n: unknown) => n is Network;
|
package/dist/network.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { USDC_ISSUER } from "./constants.js";
|
|
2
|
+
/** Circle's testnet USDC issuer (Horizon testnet home_domain centre.io, verified 2026-11-13). */
|
|
3
|
+
const TESTNET_USDC_ISSUER = "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5";
|
|
4
|
+
export const NETWORKS = Object.freeze({
|
|
5
|
+
mainnet: Object.freeze({
|
|
6
|
+
network: "mainnet",
|
|
7
|
+
passphrase: "Public Global Stellar Network ; September 2015",
|
|
8
|
+
usdcIssuer: USDC_ISSUER,
|
|
9
|
+
horizonUrl: "https://horizon.stellar.org",
|
|
10
|
+
}),
|
|
11
|
+
testnet: Object.freeze({
|
|
12
|
+
network: "testnet",
|
|
13
|
+
passphrase: "Test SDF Network ; September 2015",
|
|
14
|
+
usdcIssuer: TESTNET_USDC_ISSUER,
|
|
15
|
+
horizonUrl: "https://horizon-testnet.stellar.org",
|
|
16
|
+
}),
|
|
17
|
+
});
|
|
18
|
+
/** Runtime guard: the type says Network, but JS callers can pass anything. */
|
|
19
|
+
export const isNetwork = (n) => typeof n === "string" && Object.hasOwn(NETWORKS, n);
|
|
20
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAY7C,iGAAiG;AACjG,MAAM,mBAAmB,GAAG,0DAA0D,CAAC;AAEvF,MAAM,CAAC,MAAM,QAAQ,GAA6C,MAAM,CAAC,MAAM,CAAC;IAC9E,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;QACrB,OAAO,EAAE,SAAS;QAClB,UAAU,EAAE,gDAAgD;QAC5D,UAAU,EAAE,WAAW;QACvB,UAAU,EAAE,6BAA6B;KAC1C,CAAC;IACF,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC;QACrB,OAAO,EAAE,SAAS;QAClB,UAAU,EAAE,mCAAmC;QAC/C,UAAU,EAAE,mBAAmB;QAC/B,UAAU,EAAE,qCAAqC;KAClD,CAAC;CACH,CAAC,CAAC;AAEH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAU,EAAgB,EAAE,CACpD,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC"}
|
package/dist/ports.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Network } from "./network.js";
|
|
1
2
|
/** Injectable fetch (same shape as the global one). */
|
|
2
3
|
export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
3
4
|
/** What Spare needs to know about an account. All amounts in stroops. */
|
|
@@ -26,6 +27,8 @@ export interface AccountSnapshot {
|
|
|
26
27
|
memoRequired: boolean;
|
|
27
28
|
}
|
|
28
29
|
export interface AccountPort {
|
|
30
|
+
/** Network this port reads from. When set, Spare refuses to pair it with another network. */
|
|
31
|
+
readonly network?: Network;
|
|
29
32
|
/** Resolves null when the account does not exist. May throw on network errors. */
|
|
30
33
|
loadAccount(accountId: string): Promise<AccountSnapshot | null>;
|
|
31
34
|
}
|
package/dist/spend.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Asset, Transaction } from "@stellar/stellar-sdk";
|
|
2
|
-
|
|
2
|
+
/** Circle USDC for the selected network (default mainnet). Native has no issuer: never matches. */
|
|
3
|
+
export declare const isCircleUsdc: (a: Asset, issuer?: string) => boolean;
|
|
3
4
|
export interface Spend {
|
|
4
5
|
/** Circle-USDC the tx can spend, stroops (an upper bound for strictReceive). */
|
|
5
6
|
usdc: bigint;
|
|
@@ -17,4 +18,4 @@ export interface Spend {
|
|
|
17
18
|
* Ops that can spend but are not modelled are flagged `unsupported`; any other unknown op type
|
|
18
19
|
* sets `other` so a purchase is never mistaken for a pure USDC one.
|
|
19
20
|
*/
|
|
20
|
-
export declare function analyzeSpend(ops: Transaction["operations"]): Spend;
|
|
21
|
+
export declare function analyzeSpend(ops: Transaction["operations"], issuer?: string): Spend;
|
package/dist/spend.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { toStroops } from "./amount.js";
|
|
2
2
|
import { USDC_CODE, USDC_ISSUER } from "./constants.js";
|
|
3
|
-
|
|
3
|
+
/** Circle USDC for the selected network (default mainnet). Native has no issuer: never matches. */
|
|
4
|
+
export const isCircleUsdc = (a, issuer = USDC_ISSUER) => !a.isNative() && a.getCode() === USDC_CODE && a.getIssuer() === issuer;
|
|
4
5
|
/** Ops that move no funds out of the source for our purposes. */
|
|
5
6
|
const NO_SPEND = new Set([
|
|
6
7
|
"changeTrust", "allowTrust", "setTrustLineFlags", "setOptions", "manageData", "bumpSequence",
|
|
@@ -16,11 +17,11 @@ const UNSUPPORTED = new Set([
|
|
|
16
17
|
* Ops that can spend but are not modelled are flagged `unsupported`; any other unknown op type
|
|
17
18
|
* sets `other` so a purchase is never mistaken for a pure USDC one.
|
|
18
19
|
*/
|
|
19
|
-
export function analyzeSpend(ops) {
|
|
20
|
+
export function analyzeSpend(ops, issuer = USDC_ISSUER) {
|
|
20
21
|
const s = { usdc: 0n, xlm: 0n, other: false, uncertain: false, unsupported: false };
|
|
21
22
|
const add = (asset, amount) => {
|
|
22
23
|
const v = toStroops(amount) ?? 0n;
|
|
23
|
-
if (isCircleUsdc(asset))
|
|
24
|
+
if (isCircleUsdc(asset, issuer))
|
|
24
25
|
s.usdc += v;
|
|
25
26
|
else {
|
|
26
27
|
s.other = true;
|
package/dist/spend.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spend.js","sourceRoot":"","sources":["../src/spend.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAQ,EAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"spend.js","sourceRoot":"","sources":["../src/spend.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAExD,mGAAmG;AACnG,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAQ,EAAE,SAAiB,WAAW,EAAW,EAAE,CAC9E,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,EAAE,KAAK,MAAM,CAAC;AAezE,iEAAiE;AACjE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC;IACvB,aAAa,EAAE,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc;IAC5F,uBAAuB,EAAE,+BAA+B,EAAE,6BAA6B;IACvF,mBAAmB;CACpB,CAAC,CAAC;AAEH,qHAAqH;AACrH,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,gBAAgB,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,cAAc;CACnF,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,GAA8B,EAAE,SAAiB,WAAW;IACvF,MAAM,CAAC,GAAU,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IAC3F,MAAM,GAAG,GAAG,CAAC,KAAY,EAAE,MAAc,EAAE,EAAE;QAC3C,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAClC,IAAI,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC;YAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;aACxC,CAAC;YACJ,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;YACf,IAAI,KAAK,CAAC,QAAQ,EAAE;gBAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,CAAC;IACF,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;YAChB,KAAK,SAAS;gBAAE,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;gBAAC,MAAM;YAChD,KAAK,uBAAuB;gBAAE,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;gBAAC,MAAM;YACtE,KAAK,0BAA0B;gBAC7B,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;gBAC9B,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC;gBACnB,MAAM;YACR,KAAK,iBAAiB,CAAC;YACvB,KAAK,wBAAwB;gBAAE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;gBAAC,MAAM;YACjE,KAAK,eAAe;gBAClB,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;gBACf,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;gBAC7C,MAAM;YACR;gBACE,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC;oBAAE,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC;qBAC9C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC;oBAAE,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { FeeBumpTransaction, Transaction } from "@stellar/stellar-sdk";
|
|
2
|
+
import type { Network } from "./network.js";
|
|
2
3
|
import type { AccountPort, FetchLike, Foundation } from "./ports.js";
|
|
3
4
|
/** The tx is left untouched: Spare cannot safely modify it. */
|
|
4
5
|
export type PassthroughReason = "fee-bump" | "already-signed" | "soroban" | "multiple-sources" | "multisig" | "extra-signers";
|
|
5
6
|
/** The tx is fine but a donation must not be offered. */
|
|
6
|
-
export type NotOfferedReason = "invalid-options" | "invalid-app-id" | "invalid-amount" | "invalid-foundation" | "amount-over-cap" | "round-up-needs-usdc-purchase" | "round-up-already-whole" | "foundation-not-verified" | "foundation-trustline-missing" | "foundation-trustline-unauthorized" | "foundation-trustline-full" | "user-trustline-missing" | "user-trustline-unauthorized" | "unsupported-operation" | "multisig" | "insufficient-balance" | "account-lookup-failed" | "main-tx-not-successful";
|
|
7
|
+
export type NotOfferedReason = "invalid-options" | "network-mismatch" | "invalid-app-id" | "invalid-amount" | "invalid-foundation" | "amount-over-cap" | "round-up-needs-usdc-purchase" | "round-up-already-whole" | "foundation-not-verified" | "foundation-trustline-missing" | "foundation-trustline-unauthorized" | "foundation-trustline-full" | "user-trustline-missing" | "user-trustline-unauthorized" | "unsupported-operation" | "multisig" | "insufficient-balance" | "account-lookup-failed" | "main-tx-not-successful";
|
|
7
8
|
export interface DonationInfo {
|
|
8
9
|
/** Amount in USDC, 7 decimals. Show this to the user before signing. */
|
|
9
10
|
amount: string;
|
|
@@ -35,6 +36,12 @@ export type DonationResult = {
|
|
|
35
36
|
transaction: Transaction | FeeBumpTransaction;
|
|
36
37
|
};
|
|
37
38
|
export interface CommonOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Network the donation targets: picks the one USDC issuer Spare accepts. Default "mainnet".
|
|
41
|
+
* The tx passphrase and the account port (when it declares a network) must agree, else
|
|
42
|
+
* `not-offered` / `network-mismatch`.
|
|
43
|
+
*/
|
|
44
|
+
network?: Network;
|
|
38
45
|
foundation: Foundation;
|
|
39
46
|
appId: string;
|
|
40
47
|
/** App-set cap per donation, in USDC. */
|