@leashmarket/core 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/README.md +32 -0
- package/dist/agent/agent.d.ts +8 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +14 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/treasury-pda.d.ts +49 -0
- package/dist/agent/treasury-pda.d.ts.map +1 -0
- package/dist/agent/treasury-pda.js +55 -0
- package/dist/agent/treasury-pda.js.map +1 -0
- package/dist/explorer/index.d.ts +55 -0
- package/dist/explorer/index.d.ts.map +1 -0
- package/dist/explorer/index.js +95 -0
- package/dist/explorer/index.js.map +1 -0
- package/dist/fees/leash-fee.d.ts +248 -0
- package/dist/fees/leash-fee.d.ts.map +1 -0
- package/dist/fees/leash-fee.js +246 -0
- package/dist/fees/leash-fee.js.map +1 -0
- package/dist/format/index.d.ts +55 -0
- package/dist/format/index.d.ts.map +1 -0
- package/dist/format/index.js +130 -0
- package/dist/format/index.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/policy/evaluate.d.ts +17 -0
- package/dist/policy/evaluate.d.ts.map +1 -0
- package/dist/policy/evaluate.js +46 -0
- package/dist/policy/evaluate.js.map +1 -0
- package/dist/policy/state.d.ts +8 -0
- package/dist/policy/state.d.ts.map +1 -0
- package/dist/policy/state.js +2 -0
- package/dist/policy/state.js.map +1 -0
- package/dist/receipt/build.d.ts +5 -0
- package/dist/receipt/build.d.ts.map +1 -0
- package/dist/receipt/build.js +9 -0
- package/dist/receipt/build.js.map +1 -0
- package/dist/receipt/hash.d.ts +15 -0
- package/dist/receipt/hash.d.ts.map +1 -0
- package/dist/receipt/hash.js +40 -0
- package/dist/receipt/hash.js.map +1 -0
- package/dist/receipt/verify.d.ts +10 -0
- package/dist/receipt/verify.d.ts.map +1 -0
- package/dist/receipt/verify.js +36 -0
- package/dist/receipt/verify.js.map +1 -0
- package/dist/tokens/index.d.ts +86 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +163 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/treasury/balance.d.ts +3 -0
- package/dist/treasury/balance.d.ts.map +1 -0
- package/dist/treasury/balance.js +13 -0
- package/dist/treasury/balance.js.map +1 -0
- package/dist/treasury/inspect-token-account.d.ts +46 -0
- package/dist/treasury/inspect-token-account.d.ts.map +1 -0
- package/dist/treasury/inspect-token-account.js +67 -0
- package/dist/treasury/inspect-token-account.js.map +1 -0
- package/dist/treasury/list-balances.d.ts +57 -0
- package/dist/treasury/list-balances.d.ts.map +1 -0
- package/dist/treasury/list-balances.js +115 -0
- package/dist/treasury/list-balances.js.map +1 -0
- package/dist/treasury/pause.d.ts +32 -0
- package/dist/treasury/pause.d.ts.map +1 -0
- package/dist/treasury/pause.js +40 -0
- package/dist/treasury/pause.js.map +1 -0
- package/dist/treasury/withdraw.d.ts +13 -0
- package/dist/treasury/withdraw.d.ts.map +1 -0
- package/dist/treasury/withdraw.js +4 -0
- package/dist/treasury/withdraw.js.map +1 -0
- package/dist/wallet/index.d.ts +3 -0
- package/dist/wallet/index.d.ts.map +1 -0
- package/dist/wallet/index.js +2 -0
- package/dist/wallet/index.js.map +1 -0
- package/dist/x402/client.d.ts +72 -0
- package/dist/x402/client.d.ts.map +1 -0
- package/dist/x402/client.js +94 -0
- package/dist/x402/client.js.map +1 -0
- package/dist/x402/delegate-scheme.d.ts +107 -0
- package/dist/x402/delegate-scheme.d.ts.map +1 -0
- package/dist/x402/delegate-scheme.js +268 -0
- package/dist/x402/delegate-scheme.js.map +1 -0
- package/dist/x402/discovery.d.ts +110 -0
- package/dist/x402/discovery.d.ts.map +1 -0
- package/dist/x402/discovery.js +213 -0
- package/dist/x402/discovery.js.map +1 -0
- package/dist/x402/envelope.d.ts +65 -0
- package/dist/x402/envelope.d.ts.map +1 -0
- package/dist/x402/envelope.js +67 -0
- package/dist/x402/envelope.js.map +1 -0
- package/dist/x402/facilitator.d.ts +45 -0
- package/dist/x402/facilitator.d.ts.map +1 -0
- package/dist/x402/facilitator.js +61 -0
- package/dist/x402/facilitator.js.map +1 -0
- package/dist/x402/headers.d.ts +51 -0
- package/dist/x402/headers.d.ts.map +1 -0
- package/dist/x402/headers.js +84 -0
- package/dist/x402/headers.js.map +1 -0
- package/dist/x402/parse.d.ts +20 -0
- package/dist/x402/parse.d.ts.map +1 -0
- package/dist/x402/parse.js +31 -0
- package/dist/x402/parse.js.map +1 -0
- package/dist/x402/webhook.d.ts +48 -0
- package/dist/x402/webhook.d.ts.map +1 -0
- package/dist/x402/webhook.js +88 -0
- package/dist/x402/webhook.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @leashmarket/core
|
|
2
|
+
|
|
3
|
+
Policy evaluation, receipt hashing / chain verification, real x402 client
|
|
4
|
+
adapter for Solana, treasury helpers, and an env-based kill-switch.
|
|
5
|
+
|
|
6
|
+
```ts
|
|
7
|
+
import {
|
|
8
|
+
evaluate,
|
|
9
|
+
finalizeReceipt,
|
|
10
|
+
verifyReceiptChain,
|
|
11
|
+
treasuryPda,
|
|
12
|
+
readPauseFromEnv,
|
|
13
|
+
} from '@leashmarket/core';
|
|
14
|
+
import { createSvmBuyerFetch } from '@leashmarket/core/x402';
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`createSvmBuyerFetch({ signer, networks, rpcUrl })` registers
|
|
18
|
+
`ExactSvmScheme` (from `@x402/svm`) with `wrapFetchWithPayment` (from
|
|
19
|
+
`@x402/fetch`) and returns a `paidFetch` that handles the real x402
|
|
20
|
+
402 → sign SPL transfer → retry → settle round-trip on Solana.
|
|
21
|
+
|
|
22
|
+
All hashing uses `@noble/hashes` so the package runs unchanged in Node,
|
|
23
|
+
the browser, and edge runtimes.
|
|
24
|
+
|
|
25
|
+
## Test
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm --filter @leashmarket/core test
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
See the [`Real x402 on Solana`](../../apps/docs/standards/x402-on-solana.mdx)
|
|
32
|
+
doc for the protocol-level walkthrough.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Context, PublicKey } from '@metaplex-foundation/umi';
|
|
2
|
+
export declare class Agent {
|
|
3
|
+
readonly asset: PublicKey;
|
|
4
|
+
constructor(asset: string | PublicKey);
|
|
5
|
+
/** Asset Signer PDA (treasury) — requires Umi context for PDA derivation. */
|
|
6
|
+
treasuryPda(umi: Pick<Context, 'eddsa' | 'programs'>): PublicKey;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAGnE,qBAAa,KAAK;IAChB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;gBAEd,KAAK,EAAE,MAAM,GAAG,SAAS;IAIrC,6EAA6E;IAC7E,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG,SAAS;CAIjE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { findAssetSignerPda } from '@metaplex-foundation/mpl-core';
|
|
2
|
+
import { publicKey } from '@metaplex-foundation/umi';
|
|
3
|
+
export class Agent {
|
|
4
|
+
asset;
|
|
5
|
+
constructor(asset) {
|
|
6
|
+
this.asset = typeof asset === 'string' ? publicKey(asset) : asset;
|
|
7
|
+
}
|
|
8
|
+
/** Asset Signer PDA (treasury) — requires Umi context for PDA derivation. */
|
|
9
|
+
treasuryPda(umi) {
|
|
10
|
+
const [address] = findAssetSignerPda(umi, { asset: this.asset });
|
|
11
|
+
return address;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,MAAM,OAAO,KAAK;IACP,KAAK,CAAY;IAE1B,YAAY,KAAyB;QACnC,IAAI,CAAC,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACpE,CAAC;IAED,6EAA6E;IAC7E,WAAW,CAAC,GAAwC;QAClD,MAAM,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACjE,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kit-native helpers to derive the agent treasury (Asset Signer PDA) and the
|
|
3
|
+
* treasury's SPL token ATA for a given mint. These mirror what `mpl-core`'s
|
|
4
|
+
* `findAssetSignerPda` does (seeds = `["mpl-core-execute", asset]`, program =
|
|
5
|
+
* `CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d`) but using `@solana/kit`
|
|
6
|
+
* primitives so consumers (e.g. `@leashmarket/buyer-kit`) can derive the source
|
|
7
|
+
* token account without dragging in the Umi runtime.
|
|
8
|
+
*
|
|
9
|
+
* Used by `createBuyer` to surface precise pre-flight failure reasons
|
|
10
|
+
* (`insufficient_balance`, `insufficient_allowance`, `no_delegate`, etc.)
|
|
11
|
+
* even when the caller didn't pre-cache the source ATA.
|
|
12
|
+
*/
|
|
13
|
+
import { type Address } from '@solana/kit';
|
|
14
|
+
import { TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022';
|
|
15
|
+
import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
|
|
16
|
+
/** Metaplex Core program ID — owns the Asset Signer PDA. */
|
|
17
|
+
export declare const MPL_CORE_PROGRAM_ADDRESS: Address;
|
|
18
|
+
/**
|
|
19
|
+
* Derive the agent treasury (Asset Signer PDA) for a Metaplex Core asset.
|
|
20
|
+
*
|
|
21
|
+
* Seeds match the on-chain program: `["mpl-core-execute", asset_pubkey]`.
|
|
22
|
+
* Wire-compatible with `@metaplex-foundation/mpl-core`'s
|
|
23
|
+
* {@link findAssetSignerPda} but Umi-free.
|
|
24
|
+
*/
|
|
25
|
+
export declare function deriveAgentTreasuryAddress(asset: string | Address): Promise<Address>;
|
|
26
|
+
/**
|
|
27
|
+
* Derive the treasury's Associated Token Account for `mint`.
|
|
28
|
+
*
|
|
29
|
+
* `tokenProgram` is the SPL token program that owns this mint. **Pass it
|
|
30
|
+
* explicitly whenever the mint may be Token-2022** (e.g. USDG); the legacy
|
|
31
|
+
* default below is only correct for USDC + USDT. Helpers like
|
|
32
|
+
* {@link tokenProgramForMint} resolve this from the static stable catalog so
|
|
33
|
+
* callers don't have to spell out program addresses.
|
|
34
|
+
*
|
|
35
|
+
* Defaulting to the legacy program is intentional: an unknown mint is far
|
|
36
|
+
* more likely to be a vanilla SPL token than Token-2022, and a wrong default
|
|
37
|
+
* here surfaces as a clean `ata_missing` rather than a malformed transfer.
|
|
38
|
+
*/
|
|
39
|
+
export declare function deriveAgentTreasuryAta(args: {
|
|
40
|
+
asset: string | Address;
|
|
41
|
+
mint: string | Address;
|
|
42
|
+
tokenProgram?: Address;
|
|
43
|
+
}): Promise<{
|
|
44
|
+
treasury: Address;
|
|
45
|
+
ata: Address;
|
|
46
|
+
}>;
|
|
47
|
+
/** Re-export common token program addresses so consumers don't have to depend on both `@solana-program/*` packages. */
|
|
48
|
+
export { TOKEN_PROGRAM_ADDRESS, TOKEN_2022_PROGRAM_ADDRESS };
|
|
49
|
+
//# sourceMappingURL=treasury-pda.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treasury-pda.d.ts","sourceRoot":"","sources":["../../src/agent/treasury-pda.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAIL,KAAK,OAAO,EACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAA0B,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAChG,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,4DAA4D;AAC5D,eAAO,MAAM,wBAAwB,EAEhC,OAAO,CAAC;AAEb;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAO1F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAAC,CAM/C;AAED,uHAAuH;AACvH,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kit-native helpers to derive the agent treasury (Asset Signer PDA) and the
|
|
3
|
+
* treasury's SPL token ATA for a given mint. These mirror what `mpl-core`'s
|
|
4
|
+
* `findAssetSignerPda` does (seeds = `["mpl-core-execute", asset]`, program =
|
|
5
|
+
* `CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d`) but using `@solana/kit`
|
|
6
|
+
* primitives so consumers (e.g. `@leashmarket/buyer-kit`) can derive the source
|
|
7
|
+
* token account without dragging in the Umi runtime.
|
|
8
|
+
*
|
|
9
|
+
* Used by `createBuyer` to surface precise pre-flight failure reasons
|
|
10
|
+
* (`insufficient_balance`, `insufficient_allowance`, `no_delegate`, etc.)
|
|
11
|
+
* even when the caller didn't pre-cache the source ATA.
|
|
12
|
+
*/
|
|
13
|
+
import { address as toAddress, getAddressEncoder, getProgramDerivedAddress, } from '@solana/kit';
|
|
14
|
+
import { findAssociatedTokenPda, TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022';
|
|
15
|
+
import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
|
|
16
|
+
/** Metaplex Core program ID — owns the Asset Signer PDA. */
|
|
17
|
+
export const MPL_CORE_PROGRAM_ADDRESS = toAddress('CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d');
|
|
18
|
+
/**
|
|
19
|
+
* Derive the agent treasury (Asset Signer PDA) for a Metaplex Core asset.
|
|
20
|
+
*
|
|
21
|
+
* Seeds match the on-chain program: `["mpl-core-execute", asset_pubkey]`.
|
|
22
|
+
* Wire-compatible with `@metaplex-foundation/mpl-core`'s
|
|
23
|
+
* {@link findAssetSignerPda} but Umi-free.
|
|
24
|
+
*/
|
|
25
|
+
export async function deriveAgentTreasuryAddress(asset) {
|
|
26
|
+
const assetAddress = typeof asset === 'string' ? toAddress(asset) : asset;
|
|
27
|
+
const [pda] = await getProgramDerivedAddress({
|
|
28
|
+
programAddress: MPL_CORE_PROGRAM_ADDRESS,
|
|
29
|
+
seeds: [new TextEncoder().encode('mpl-core-execute'), getAddressEncoder().encode(assetAddress)],
|
|
30
|
+
});
|
|
31
|
+
return pda;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Derive the treasury's Associated Token Account for `mint`.
|
|
35
|
+
*
|
|
36
|
+
* `tokenProgram` is the SPL token program that owns this mint. **Pass it
|
|
37
|
+
* explicitly whenever the mint may be Token-2022** (e.g. USDG); the legacy
|
|
38
|
+
* default below is only correct for USDC + USDT. Helpers like
|
|
39
|
+
* {@link tokenProgramForMint} resolve this from the static stable catalog so
|
|
40
|
+
* callers don't have to spell out program addresses.
|
|
41
|
+
*
|
|
42
|
+
* Defaulting to the legacy program is intentional: an unknown mint is far
|
|
43
|
+
* more likely to be a vanilla SPL token than Token-2022, and a wrong default
|
|
44
|
+
* here surfaces as a clean `ata_missing` rather than a malformed transfer.
|
|
45
|
+
*/
|
|
46
|
+
export async function deriveAgentTreasuryAta(args) {
|
|
47
|
+
const treasury = await deriveAgentTreasuryAddress(args.asset);
|
|
48
|
+
const mint = typeof args.mint === 'string' ? toAddress(args.mint) : args.mint;
|
|
49
|
+
const tokenProgram = args.tokenProgram ?? TOKEN_PROGRAM_ADDRESS;
|
|
50
|
+
const [ata] = await findAssociatedTokenPda({ mint, owner: treasury, tokenProgram });
|
|
51
|
+
return { treasury, ata };
|
|
52
|
+
}
|
|
53
|
+
/** Re-export common token program addresses so consumers don't have to depend on both `@solana-program/*` packages. */
|
|
54
|
+
export { TOKEN_PROGRAM_ADDRESS, TOKEN_2022_PROGRAM_ADDRESS };
|
|
55
|
+
//# sourceMappingURL=treasury-pda.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treasury-pda.js","sourceRoot":"","sources":["../../src/agent/treasury-pda.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EACL,OAAO,IAAI,SAAS,EACpB,iBAAiB,EACjB,wBAAwB,GAEzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAChG,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,4DAA4D;AAC5D,MAAM,CAAC,MAAM,wBAAwB,GAAG,SAAS,CAC/C,8CAA8C,CACpC,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,KAAuB;IACtE,MAAM,YAAY,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAE,SAAS,CAAC,KAAK,CAAa,CAAC,CAAC,CAAC,KAAK,CAAC;IACvF,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,wBAAwB,CAAC;QAC3C,cAAc,EAAE,wBAAwB;QACxC,KAAK,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;KAChG,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAI5C;IACC,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IAC3F,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,qBAAqB,CAAC;IAChE,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,sBAAsB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;IACpF,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AAC3B,CAAC;AAED,uHAAuH;AACvH,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explorer URL builders for Solana addresses, transactions, and Metaplex
|
|
3
|
+
* Core agent assets. Used by Leash to stamp `tx_explorer` /
|
|
4
|
+
* `agent_explorer` links into x402 response headers and to render "View on
|
|
5
|
+
* Solscan" affordances in the playground UI.
|
|
6
|
+
*
|
|
7
|
+
* We default to Solscan (best UX for SPL transfers and Core assets) but
|
|
8
|
+
* support `solana-explorer` (the official explorer.solana.com) as well.
|
|
9
|
+
*/
|
|
10
|
+
import type { TokenNetwork } from '../tokens/index.js';
|
|
11
|
+
export type ExplorerProvider = 'solscan' | 'solana-explorer';
|
|
12
|
+
export type ExplorerOptions = {
|
|
13
|
+
/** Defaults to `'devnet'`. Mainnet links omit the `?cluster=` param. */
|
|
14
|
+
network?: TokenNetwork;
|
|
15
|
+
/** Defaults to `'solscan'`. */
|
|
16
|
+
provider?: ExplorerProvider;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Explorer page for an SPL token transfer / x402 settlement. Returns
|
|
20
|
+
* `null` when no signature is supplied so callers can pipe through `null`
|
|
21
|
+
* fields from receipts without nullish-checking inline.
|
|
22
|
+
*/
|
|
23
|
+
export declare function transactionExplorerUrl(signature: string | null | undefined, opts?: ExplorerOptions): string | null;
|
|
24
|
+
/** Explorer page for a Metaplex Core agent asset (the agent mint address). */
|
|
25
|
+
export declare function agentExplorerUrl(mint: string | null | undefined, opts?: ExplorerOptions): string | null;
|
|
26
|
+
/** Explorer page for any Solana account / mint / PDA. */
|
|
27
|
+
export declare function addressExplorerUrl(address: string | null | undefined, opts?: ExplorerOptions): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Default base for the Leash protocol explorer. Override via the
|
|
30
|
+
* `baseUrl` option (or `LEASH_EXPLORER_URL` upstream) when running
|
|
31
|
+
* against a self-hosted explorer or a staging deployment.
|
|
32
|
+
*/
|
|
33
|
+
export declare const LEASH_EXPLORER_DEFAULT = "https://explorer.leash.market";
|
|
34
|
+
/**
|
|
35
|
+
* Page on `explorer.leash.market` for a Leash receipt hash. Returns
|
|
36
|
+
* `null` when no hash is supplied so callers can pipe through nullable
|
|
37
|
+
* fields without inline checks.
|
|
38
|
+
*
|
|
39
|
+
* The hash should be the seller-side (canonical) `receipt_hash` — the
|
|
40
|
+
* one stamped on the response via `X-Leash-Receipt-Hash`. The
|
|
41
|
+
* buyer-kit's locally-computed hash is per-buyer-view and the explorer
|
|
42
|
+
* does not index it.
|
|
43
|
+
*/
|
|
44
|
+
export declare function leashReceiptUrl(hash: string | null | undefined, opts?: {
|
|
45
|
+
baseUrl?: string;
|
|
46
|
+
}): string | null;
|
|
47
|
+
/** Page on `explorer.leash.market` for a Solana tx signature. */
|
|
48
|
+
export declare function leashTxUrl(signature: string | null | undefined, opts?: {
|
|
49
|
+
baseUrl?: string;
|
|
50
|
+
}): string | null;
|
|
51
|
+
/** Page on `explorer.leash.market` for an agent (MPL Core asset). */
|
|
52
|
+
export declare function leashAgentUrl(mint: string | null | undefined, opts?: {
|
|
53
|
+
baseUrl?: string;
|
|
54
|
+
}): string | null;
|
|
55
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/explorer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,iBAAiB,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG;IAC5B,wEAAwE;IACxE,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B,CAAC;AAYF;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,IAAI,GAAE,eAAoB,GACzB,MAAM,GAAG,IAAI,CAKf;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,IAAI,GAAE,eAAoB,GACzB,MAAM,GAAG,IAAI,CAMf;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,IAAI,GAAE,eAAoB,GACzB,MAAM,GAAG,IAAI,CAMf;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,kCAAkC,CAAC;AAEtE;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9B,MAAM,GAAG,IAAI,CAMf;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9B,MAAM,GAAG,IAAI,CAMf;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9B,MAAM,GAAG,IAAI,CAMf"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explorer URL builders for Solana addresses, transactions, and Metaplex
|
|
3
|
+
* Core agent assets. Used by Leash to stamp `tx_explorer` /
|
|
4
|
+
* `agent_explorer` links into x402 response headers and to render "View on
|
|
5
|
+
* Solscan" affordances in the playground UI.
|
|
6
|
+
*
|
|
7
|
+
* We default to Solscan (best UX for SPL transfers and Core assets) but
|
|
8
|
+
* support `solana-explorer` (the official explorer.solana.com) as well.
|
|
9
|
+
*/
|
|
10
|
+
function clusterParam(network, provider) {
|
|
11
|
+
if (network === 'mainnet')
|
|
12
|
+
return '';
|
|
13
|
+
if (provider === 'solscan')
|
|
14
|
+
return '?cluster=devnet';
|
|
15
|
+
return '?cluster=devnet';
|
|
16
|
+
}
|
|
17
|
+
function base(provider) {
|
|
18
|
+
return provider === 'solscan' ? 'https://solscan.io' : 'https://explorer.solana.com';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Explorer page for an SPL token transfer / x402 settlement. Returns
|
|
22
|
+
* `null` when no signature is supplied so callers can pipe through `null`
|
|
23
|
+
* fields from receipts without nullish-checking inline.
|
|
24
|
+
*/
|
|
25
|
+
export function transactionExplorerUrl(signature, opts = {}) {
|
|
26
|
+
if (!signature)
|
|
27
|
+
return null;
|
|
28
|
+
const provider = opts.provider ?? 'solscan';
|
|
29
|
+
const network = opts.network ?? 'devnet';
|
|
30
|
+
return `${base(provider)}/tx/${signature}${clusterParam(network, provider)}`;
|
|
31
|
+
}
|
|
32
|
+
/** Explorer page for a Metaplex Core agent asset (the agent mint address). */
|
|
33
|
+
export function agentExplorerUrl(mint, opts = {}) {
|
|
34
|
+
if (!mint)
|
|
35
|
+
return null;
|
|
36
|
+
// Core assets are addresses, so the address page gives the richest view
|
|
37
|
+
// (asset metadata + holder history). Solscan also accepts /token but
|
|
38
|
+
// /address surfaces the Core attributes plate.
|
|
39
|
+
return addressExplorerUrl(mint, opts);
|
|
40
|
+
}
|
|
41
|
+
/** Explorer page for any Solana account / mint / PDA. */
|
|
42
|
+
export function addressExplorerUrl(address, opts = {}) {
|
|
43
|
+
if (!address)
|
|
44
|
+
return null;
|
|
45
|
+
const provider = opts.provider ?? 'solscan';
|
|
46
|
+
const network = opts.network ?? 'devnet';
|
|
47
|
+
const path = provider === 'solscan' ? 'account' : 'address';
|
|
48
|
+
return `${base(provider)}/${path}/${address}${clusterParam(network, provider)}`;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Default base for the Leash protocol explorer. Override via the
|
|
52
|
+
* `baseUrl` option (or `LEASH_EXPLORER_URL` upstream) when running
|
|
53
|
+
* against a self-hosted explorer or a staging deployment.
|
|
54
|
+
*/
|
|
55
|
+
export const LEASH_EXPLORER_DEFAULT = 'https://explorer.leash.market';
|
|
56
|
+
/**
|
|
57
|
+
* Page on `explorer.leash.market` for a Leash receipt hash. Returns
|
|
58
|
+
* `null` when no hash is supplied so callers can pipe through nullable
|
|
59
|
+
* fields without inline checks.
|
|
60
|
+
*
|
|
61
|
+
* The hash should be the seller-side (canonical) `receipt_hash` — the
|
|
62
|
+
* one stamped on the response via `X-Leash-Receipt-Hash`. The
|
|
63
|
+
* buyer-kit's locally-computed hash is per-buyer-view and the explorer
|
|
64
|
+
* does not index it.
|
|
65
|
+
*/
|
|
66
|
+
export function leashReceiptUrl(hash, opts = {}) {
|
|
67
|
+
if (!hash)
|
|
68
|
+
return null;
|
|
69
|
+
const trimmed = hash.trim();
|
|
70
|
+
if (trimmed.length === 0)
|
|
71
|
+
return null;
|
|
72
|
+
const base = (opts.baseUrl ?? LEASH_EXPLORER_DEFAULT).replace(/\/+$/, '');
|
|
73
|
+
return `${base}/receipt/${encodeURIComponent(trimmed)}`;
|
|
74
|
+
}
|
|
75
|
+
/** Page on `explorer.leash.market` for a Solana tx signature. */
|
|
76
|
+
export function leashTxUrl(signature, opts = {}) {
|
|
77
|
+
if (!signature)
|
|
78
|
+
return null;
|
|
79
|
+
const trimmed = signature.trim();
|
|
80
|
+
if (trimmed.length === 0)
|
|
81
|
+
return null;
|
|
82
|
+
const base = (opts.baseUrl ?? LEASH_EXPLORER_DEFAULT).replace(/\/+$/, '');
|
|
83
|
+
return `${base}/tx/${encodeURIComponent(trimmed)}`;
|
|
84
|
+
}
|
|
85
|
+
/** Page on `explorer.leash.market` for an agent (MPL Core asset). */
|
|
86
|
+
export function leashAgentUrl(mint, opts = {}) {
|
|
87
|
+
if (!mint)
|
|
88
|
+
return null;
|
|
89
|
+
const trimmed = mint.trim();
|
|
90
|
+
if (trimmed.length === 0)
|
|
91
|
+
return null;
|
|
92
|
+
const base = (opts.baseUrl ?? LEASH_EXPLORER_DEFAULT).replace(/\/+$/, '');
|
|
93
|
+
return `${base}/agent/${encodeURIComponent(trimmed)}`;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/explorer/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leash protocol fee primitives.
|
|
3
|
+
*
|
|
4
|
+
* Every Leash-flavoured x402 settlement levies a small protocol fee on
|
|
5
|
+
* top of the seller's quoted price. The buyer signs **one** transaction
|
|
6
|
+
* with **two** `TransferChecked` instructions — one to the seller's
|
|
7
|
+
* `payTo` ATA, one to the Leash treasury's ATA on the same mint — so
|
|
8
|
+
* both legs settle atomically (either both transfers land or neither
|
|
9
|
+
* does). The fee leg is funded out of the same source token account as
|
|
10
|
+
* the seller leg.
|
|
11
|
+
*
|
|
12
|
+
* This module is the shared building block:
|
|
13
|
+
* - {@link LEASH_FEE_BPS_DEFAULT} — 100 bps (1%) by default; overridable
|
|
14
|
+
* by env at the seller (which advertises the fee in `extra['leash.fee']`)
|
|
15
|
+
* and at the facilitator (which enforces it on `verify` / `settle`).
|
|
16
|
+
* - {@link computeFeeAtoms} — `ceilBps(amount, bps)`. Always rounds the
|
|
17
|
+
* fee **up** so dust never leaks out of the treasury when the buyer
|
|
18
|
+
* pays a non-divisible price.
|
|
19
|
+
* - {@link LeashFeeExtra} — wire shape stamped onto `paymentRequirements.extra`
|
|
20
|
+
* so buyer + facilitator agree on bps, amount, mint authority, and ATA.
|
|
21
|
+
* - {@link resolveLeashFeeAuthority} — env-driven lookup of the treasury
|
|
22
|
+
* authority pubkey per network (mainnet / devnet).
|
|
23
|
+
* - {@link getLeashFeeAtaFor} — derive the treasury's ATA for a given
|
|
24
|
+
* `(asset, tokenProgram)` pair so seller + facilitator both end up
|
|
25
|
+
* with the same destination address.
|
|
26
|
+
*
|
|
27
|
+
* Fee math is gross-up:
|
|
28
|
+
* - Seller quotes `net` (e.g. 1 USDC = 1_000_000 atoms).
|
|
29
|
+
* - Buyer pays `gross = net + fee` where `fee = ceil(net * bps / 10_000)`.
|
|
30
|
+
* - At 100 bps: 1 USDC → buyer signs 1.01 USDC; 1.00 USDC lands in seller
|
|
31
|
+
* ATA, 0.01 USDC lands in treasury ATA.
|
|
32
|
+
*
|
|
33
|
+
* Env vars (read at process boot — never inline a stale value):
|
|
34
|
+
* - `LEASH_FEE_BPS` — global default (integer 0..1000). Default 100.
|
|
35
|
+
* - `LEASH_FEE_ENFORCE` — `off | warn | enforce`. Default `warn`.
|
|
36
|
+
* - `LEASH_FEE_ENFORCE_MAINNET` — per-network override; falls back to LEASH_FEE_ENFORCE.
|
|
37
|
+
* - `LEASH_FEE_ENFORCE_DEVNET` — per-network override; falls back to LEASH_FEE_ENFORCE.
|
|
38
|
+
* - `LEASH_FEE_AUTHORITY_MAINNET`— wallet pubkey that owns the mainnet fee ATAs.
|
|
39
|
+
* - `LEASH_FEE_AUTHORITY_DEVNET` — wallet pubkey that owns the devnet fee ATAs.
|
|
40
|
+
*
|
|
41
|
+
* Defaults bake in `3DdcJkvjW7KLtMeko3Zr57jEJWhqRHuPsEBFm1XJYh7W` on both
|
|
42
|
+
* clusters so a fresh deploy collects fees out of the box. Override via
|
|
43
|
+
* env to rotate the treasury without code changes.
|
|
44
|
+
*/
|
|
45
|
+
import { type Address } from '@solana/kit';
|
|
46
|
+
import type { TokenNetwork } from '../tokens/index.js';
|
|
47
|
+
/**
|
|
48
|
+
* Default protocol fee rate in basis points (1 bps = 0.01%). 100 bps = 1%.
|
|
49
|
+
* Used by both the seller-kit (when stamping `extra['leash.fee']`) and
|
|
50
|
+
* the facilitator (when verifying inbound payment payloads). Override
|
|
51
|
+
* per-network via the `LEASH_FEE_BPS` env var on both surfaces.
|
|
52
|
+
*/
|
|
53
|
+
export declare const LEASH_FEE_BPS_DEFAULT = 100;
|
|
54
|
+
/**
|
|
55
|
+
* Default treasury authority on Solana mainnet. Owns the SPL token
|
|
56
|
+
* accounts (one ATA per stable mint) where Leash collects protocol fees.
|
|
57
|
+
* Set `LEASH_FEE_AUTHORITY_MAINNET` to override (e.g. when migrating to
|
|
58
|
+
* a multisig).
|
|
59
|
+
*/
|
|
60
|
+
export declare const LEASH_FEE_AUTHORITY_MAINNET_DEFAULT = "3DdcJkvjW7KLtMeko3Zr57jEJWhqRHuPsEBFm1XJYh7W";
|
|
61
|
+
/**
|
|
62
|
+
* Default treasury authority on Solana devnet. Same key as mainnet by
|
|
63
|
+
* design — devnet uses a separate ATA per mint anyway, so reusing the
|
|
64
|
+
* authority just simplifies operational tooling. Override via
|
|
65
|
+
* `LEASH_FEE_AUTHORITY_DEVNET`.
|
|
66
|
+
*/
|
|
67
|
+
export declare const LEASH_FEE_AUTHORITY_DEVNET_DEFAULT = "3DdcJkvjW7KLtMeko3Zr57jEJWhqRHuPsEBFm1XJYh7W";
|
|
68
|
+
/**
|
|
69
|
+
* Enforcement modes for the Leash protocol fee.
|
|
70
|
+
*
|
|
71
|
+
* - `off` — facilitator ignores fee logic entirely. Vanilla x402
|
|
72
|
+
* transactions verify exactly as before. Sellers that stamp
|
|
73
|
+
* a fee `extra` still get one through, but the facilitator
|
|
74
|
+
* will treat the second leg as an unknown instruction and
|
|
75
|
+
* reject it. Use only for tests / local dev.
|
|
76
|
+
* - `warn` — facilitator accepts both vanilla and fee-bearing payloads.
|
|
77
|
+
* If a fee payload is malformed (wrong amount, wrong dest,
|
|
78
|
+
* wrong authority), it logs and accepts. Use during the
|
|
79
|
+
* rollout window where third-party clients haven't shipped
|
|
80
|
+
* the upgrade yet.
|
|
81
|
+
* - `enforce` — facilitator REJECTS any payload that doesn't carry a
|
|
82
|
+
* valid fee leg. The default once mainnet rollout is done.
|
|
83
|
+
*
|
|
84
|
+
* Default is `warn` so the upgrade lands without breaking older buyers.
|
|
85
|
+
*/
|
|
86
|
+
export type LeashFeeEnforcement = 'off' | 'warn' | 'enforce';
|
|
87
|
+
/**
|
|
88
|
+
* Wire shape of the `paymentRequirements.extra['leash.fee']` block.
|
|
89
|
+
*
|
|
90
|
+
* Compact and sync-stampable: only the **static** fee parameters
|
|
91
|
+
* travel on the wire (`bps`, `feeAuthority`). The buyer + facilitator
|
|
92
|
+
* derive everything else (`feeAtomic`, `grossAtomic`, `feeDestination`)
|
|
93
|
+
* on demand from `(paymentRequirements.amount, asset, tokenProgram)`
|
|
94
|
+
* via {@link computeLeashFeeForRequirements} so all three surfaces
|
|
95
|
+
* agree byte-for-byte without any round-tripping.
|
|
96
|
+
*
|
|
97
|
+
* Sync stamping matters because seller-kit's `createSeller(...)` is
|
|
98
|
+
* a sync setup-time call; making it async would cascade through every
|
|
99
|
+
* downstream caller (web playground, demos, docs, tests).
|
|
100
|
+
*/
|
|
101
|
+
export type LeashFeeExtra = {
|
|
102
|
+
/**
|
|
103
|
+
* Discriminator. Always `'1'`. Bump when the wire shape changes so
|
|
104
|
+
* older facilitators reject incompatible payloads cleanly.
|
|
105
|
+
*/
|
|
106
|
+
v: '1';
|
|
107
|
+
/**
|
|
108
|
+
* Fee rate in basis points the seller priced this `accepts[]` entry
|
|
109
|
+
* for (e.g. `100` for 1%). Sellers and facilitators must agree.
|
|
110
|
+
*/
|
|
111
|
+
bps: number;
|
|
112
|
+
/**
|
|
113
|
+
* Treasury authority pubkey (the wallet that owns the destination
|
|
114
|
+
* fee ATA). Must match the env-configured authority on the
|
|
115
|
+
* facilitator side or verify will reject.
|
|
116
|
+
*/
|
|
117
|
+
feeAuthority: string;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Compute the fee in atomic units for a given seller amount + bps,
|
|
121
|
+
* rounding **up** (`ceil`) so dust never leaks out of the treasury.
|
|
122
|
+
*
|
|
123
|
+
* Examples (bps=100):
|
|
124
|
+
* - amount=1_000_000 → fee=10_000 (0.01 USDC for 1.00 USDC)
|
|
125
|
+
* - amount=1 → fee=1 (1 atom for 1 atom — ceil)
|
|
126
|
+
* - amount=999 → fee=10 (10 atoms for 999 atoms — ceil)
|
|
127
|
+
*
|
|
128
|
+
* @param amount seller leg amount in atomic units
|
|
129
|
+
* @param bps integer 0..10_000
|
|
130
|
+
* @returns atomic fee amount, never negative
|
|
131
|
+
*/
|
|
132
|
+
export declare function computeFeeAtoms(amount: bigint, bps: number): bigint;
|
|
133
|
+
/**
|
|
134
|
+
* Convenience: given a `net` (seller's quoted) amount, return the
|
|
135
|
+
* `(net, fee, gross)` triple where `gross = net + fee` and
|
|
136
|
+
* `fee = ceilBps(net, bps)`.
|
|
137
|
+
*
|
|
138
|
+
* Use at seller-kit's `buildAccepts` time and on the buyer playground
|
|
139
|
+
* UI to render "you will pay X" disclosures.
|
|
140
|
+
*/
|
|
141
|
+
export declare function applyFeeGrossUp(netAmount: bigint, bps?: number): {
|
|
142
|
+
net: bigint;
|
|
143
|
+
fee: bigint;
|
|
144
|
+
gross: bigint;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Read the configured fee bps from env. Falls back to
|
|
148
|
+
* {@link LEASH_FEE_BPS_DEFAULT} when unset / unparseable. Validates
|
|
149
|
+
* the range so a bad env never surfaces as a 50_000 bps fee.
|
|
150
|
+
*/
|
|
151
|
+
export declare function resolveLeashFeeBps(): number;
|
|
152
|
+
/**
|
|
153
|
+
* Read the configured fee authority for the given network from env.
|
|
154
|
+
* Falls back to the bundled defaults
|
|
155
|
+
* ({@link LEASH_FEE_AUTHORITY_MAINNET_DEFAULT} /
|
|
156
|
+
* {@link LEASH_FEE_AUTHORITY_DEVNET_DEFAULT}) when unset.
|
|
157
|
+
*/
|
|
158
|
+
export declare function resolveLeashFeeAuthority(network: TokenNetwork): string;
|
|
159
|
+
/**
|
|
160
|
+
* Read the enforcement mode for the given network from env. Per-network
|
|
161
|
+
* vars override the global one. Default is `warn` everywhere so the
|
|
162
|
+
* rollout doesn't break older clients overnight.
|
|
163
|
+
*/
|
|
164
|
+
export declare function resolveLeashFeeEnforcement(network: TokenNetwork): LeashFeeEnforcement;
|
|
165
|
+
/**
|
|
166
|
+
* Treasury ATA descriptor. `ata` is the on-chain associated token
|
|
167
|
+
* account address (where fees land); `authority` is the wallet that
|
|
168
|
+
* owns it (the fee-payer for any future treasury sweep).
|
|
169
|
+
*/
|
|
170
|
+
export type LeashFeeAccount = {
|
|
171
|
+
ata: Address;
|
|
172
|
+
authority: Address;
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* Derive the Leash fee ATA on the given `(network, asset, tokenProgram)`.
|
|
176
|
+
* Both the seller (when stamping `extra['leash.fee'].feeDestination`)
|
|
177
|
+
* and the facilitator (when verifying the second `TransferChecked`)
|
|
178
|
+
* call this so they always agree on the destination.
|
|
179
|
+
*/
|
|
180
|
+
export declare function getLeashFeeAtaFor(args: {
|
|
181
|
+
network: TokenNetwork;
|
|
182
|
+
/** SPL mint address the seller is collecting in. */
|
|
183
|
+
asset: string;
|
|
184
|
+
/**
|
|
185
|
+
* Token program owning the mint. Pass `'spl-token'` for legacy
|
|
186
|
+
* USDC/USDT and `'spl-token-2022'` for Token-2022 mints (USDG, etc.).
|
|
187
|
+
*/
|
|
188
|
+
tokenProgram: 'spl-token' | 'spl-token-2022';
|
|
189
|
+
/** Optional override; defaults to {@link resolveLeashFeeAuthority}. */
|
|
190
|
+
authority?: string;
|
|
191
|
+
}): Promise<LeashFeeAccount>;
|
|
192
|
+
/**
|
|
193
|
+
* Build the static `extra['leash.fee']` payload for a given seller leg.
|
|
194
|
+
*
|
|
195
|
+
* Sync by construction: the wire shape only carries `bps` and
|
|
196
|
+
* `feeAuthority`, so seller-kit / payment-links can stamp this at
|
|
197
|
+
* `buildAccepts` time without making `createSeller` async. The buyer +
|
|
198
|
+
* facilitator derive the dynamic fields (`feeAtomic`, `grossAtomic`,
|
|
199
|
+
* `feeDestination`) on demand via {@link computeLeashFeeForRequirements}.
|
|
200
|
+
*/
|
|
201
|
+
export declare function buildLeashFeeExtra(args: {
|
|
202
|
+
network: TokenNetwork;
|
|
203
|
+
/** Defaults to {@link resolveLeashFeeBps}. */
|
|
204
|
+
bps?: number;
|
|
205
|
+
/** Defaults to {@link resolveLeashFeeAuthority}. */
|
|
206
|
+
authority?: string;
|
|
207
|
+
}): LeashFeeExtra;
|
|
208
|
+
/**
|
|
209
|
+
* Type guard + parser for an inbound `extra['leash.fee']` block. Returns
|
|
210
|
+
* `null` if the value is absent or malformed (any field missing /
|
|
211
|
+
* wrong type / out-of-range bps). Facilitators use this to decide whether
|
|
212
|
+
* to apply fee verification.
|
|
213
|
+
*/
|
|
214
|
+
export declare function parseLeashFeeExtra(extra: Record<string, unknown> | null | undefined): LeashFeeExtra | null;
|
|
215
|
+
/**
|
|
216
|
+
* Resolved fee for a specific `paymentRequirements` entry. Buyer scheme
|
|
217
|
+
* + facilitator scheme both call {@link computeLeashFeeForRequirements}
|
|
218
|
+
* and then trust this exact triple, so they always agree.
|
|
219
|
+
*/
|
|
220
|
+
export type ResolvedLeashFee = {
|
|
221
|
+
bps: number;
|
|
222
|
+
feeAtomic: bigint;
|
|
223
|
+
grossAtomic: bigint;
|
|
224
|
+
feeAuthority: Address;
|
|
225
|
+
feeDestination: Address;
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* Resolve the per-request fee triple `(bps, feeAtomic, feeDestination)`
|
|
229
|
+
* for a given `paymentRequirements` entry. Returns `null` if the
|
|
230
|
+
* requirement carries no `extra['leash.fee']` (vanilla x402 mode).
|
|
231
|
+
*
|
|
232
|
+
* Both the buyer (when constructing the `TransferChecked` fee leg) and
|
|
233
|
+
* the facilitator (when verifying the inbound transaction) call this
|
|
234
|
+
* function so they always derive the same destination ATA + atomic
|
|
235
|
+
* amount from the same inputs.
|
|
236
|
+
*/
|
|
237
|
+
export declare function computeLeashFeeForRequirements(args: {
|
|
238
|
+
network: TokenNetwork;
|
|
239
|
+
/** SPL mint address (`paymentRequirements.asset`). */
|
|
240
|
+
asset: string;
|
|
241
|
+
/** Token program owning the mint. */
|
|
242
|
+
tokenProgram: 'spl-token' | 'spl-token-2022';
|
|
243
|
+
/** Seller leg amount in atomic units (`paymentRequirements.maxAmountRequired`). */
|
|
244
|
+
amount: string;
|
|
245
|
+
/** Parsed `extra['leash.fee']`. Pass `null` when absent. */
|
|
246
|
+
extra: LeashFeeExtra | null;
|
|
247
|
+
}): Promise<ResolvedLeashFee | null>;
|
|
248
|
+
//# sourceMappingURL=leash-fee.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leash-fee.d.ts","sourceRoot":"","sources":["../../src/fees/leash-fee.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAIjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,iDAAiD,CAAC;AAElG;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,iDAAiD,CAAC;AAEjG;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;;OAGG;IACH,CAAC,EAAE,GAAG,CAAC;IACP;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAWnE;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAA8B,GAClC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAG7C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAW3C;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAUtE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,YAAY,GAAG,mBAAmB,CAUrF;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,OAAO,EAAE,YAAY,CAAC;IACtB,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,YAAY,EAAE,WAAW,GAAG,gBAAgB,CAAC;IAC7C,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,eAAe,CAAC,CAU3B;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,OAAO,EAAE,YAAY,CAAC;IACtB,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,aAAa,CAIhB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAChD,aAAa,GAAG,IAAI,CAkBtB;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAsB,8BAA8B,CAAC,IAAI,EAAE;IACzD,OAAO,EAAE,YAAY,CAAC;IACtB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,YAAY,EAAE,WAAW,GAAG,gBAAgB,CAAC;IAC7C,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;CAC7B,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAkBnC"}
|