@m2m-monster/core 0.1.0 → 1.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 +2 -2
- package/dist/errors.d.ts +1 -0
- package/dist/errors.js +1 -0
- package/dist/networks.d.ts +4 -1
- package/dist/networks.js +3 -0
- package/dist/split.js +7 -3
- package/dist/test-rpc.d.ts +7 -0
- package/dist/test-rpc.js +28 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @m2m-monster/core
|
|
2
2
|
|
|
3
|
-
Core of [m2m.monster](https://
|
|
3
|
+
Core of [m2m.monster](https://m2m.monster/llms.txt), used by `@m2m-monster/sdk` and `@m2m-monster/mcp`: fee formulas, signed quotes and receipts, mint whitelists, and building and strict verification of the `m2m-split` transaction for x402 on Solana.
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> Most agents want `@m2m-monster/sdk`.
|
|
6
6
|
|
|
7
7
|
License: Apache-2.0
|
package/dist/errors.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export declare const ERRORS: {
|
|
|
16
16
|
readonly CHALLENGE_INVALID: "The registration challenge is missing, expired, already used, or not signed by this public key.";
|
|
17
17
|
readonly IDEMPOTENCY_KEY_REUSED: "The idempotency key was already used for a different request.";
|
|
18
18
|
readonly INTERNAL_ERROR: "Internal error. Retry later.";
|
|
19
|
+
readonly PAYMENT_STATUS_UNKNOWN: "The status of a signed payment could not be determined. Do not pay again; retry later.";
|
|
19
20
|
};
|
|
20
21
|
export type ErrorCode = keyof typeof ERRORS;
|
|
21
22
|
export declare class M2mError extends Error {
|
package/dist/errors.js
CHANGED
|
@@ -17,6 +17,7 @@ export const ERRORS = {
|
|
|
17
17
|
CHALLENGE_INVALID: "The registration challenge is missing, expired, already used, or not signed by this public key.",
|
|
18
18
|
IDEMPOTENCY_KEY_REUSED: "The idempotency key was already used for a different request.",
|
|
19
19
|
INTERNAL_ERROR: "Internal error. Retry later.",
|
|
20
|
+
PAYMENT_STATUS_UNKNOWN: "The status of a signed payment could not be determined. Do not pay again; retry later.",
|
|
20
21
|
};
|
|
21
22
|
export class M2mError extends Error {
|
|
22
23
|
code;
|
package/dist/networks.d.ts
CHANGED
|
@@ -9,7 +9,10 @@ export interface NetworkConfig {
|
|
|
9
9
|
name: string;
|
|
10
10
|
/** USDC mint: the only token the fee is paid in (rule 5). */
|
|
11
11
|
usdc: string;
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Treasury wallet: single-key, multisig planned as the project grows (rule 9). Only its public
|
|
14
|
+
* address is known here; no server holds its key. The API refuses to start without a valid one.
|
|
15
|
+
*/
|
|
13
16
|
treasury?: string;
|
|
14
17
|
mints: readonly AllowedMint[];
|
|
15
18
|
}
|
package/dist/networks.js
CHANGED
|
@@ -5,6 +5,9 @@ export const DEVNET = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
|
|
|
5
5
|
export const NETWORKS = {
|
|
6
6
|
[MAINNET]: {
|
|
7
7
|
name: "solana-mainnet",
|
|
8
|
+
// Provided by the user on 2026-10-15 (D58); its USDC account (classic SPL Token ATA) is
|
|
9
|
+
// EWQ5w4DPmkinV4iHn9H7pcwx5Q8fYQCnY46CzGD1ErTk.
|
|
10
|
+
treasury: "D68nkVrQD3pcs6qNcadXqWvoKqsNCKpLemy3zYVmGHym",
|
|
8
11
|
usdc: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
9
12
|
mints: [
|
|
10
13
|
{ symbol: "USDC", mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" },
|
package/dist/split.js
CHANGED
|
@@ -74,6 +74,8 @@ async function checkTransfer(index, ix, payer, expected) {
|
|
|
74
74
|
const fail = (what) => invalid(`instruction ${index}: ${what}`);
|
|
75
75
|
if (ix.programAddress !== TOKEN_PROGRAM_ADDRESS ||
|
|
76
76
|
ix.data[0] !== 12 ||
|
|
77
|
+
// u8 discriminator + u64 amount + u8 decimals: no trailing bytes.
|
|
78
|
+
ix.data.length !== 10 ||
|
|
77
79
|
ix.accounts.length !== 4) {
|
|
78
80
|
throw fail("expected a TransferChecked of the SPL Token program");
|
|
79
81
|
}
|
|
@@ -119,12 +121,14 @@ export async function verifySplitTransaction(wire, expected, options) {
|
|
|
119
121
|
if (instructions.length !== 5)
|
|
120
122
|
throw invalid("expected exactly 5 instructions");
|
|
121
123
|
const [limitIx, priceIx, paymentIx, feeIx, memoIx] = instructions;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
[
|
|
124
|
+
// Exact data lengths: no trailing bytes (u8 discriminator + u32 units / u64 micro-lamports).
|
|
125
|
+
for (const [index, ix, discriminator, size] of [
|
|
126
|
+
[0, limitIx, 2, 5],
|
|
127
|
+
[1, priceIx, 3, 9],
|
|
125
128
|
]) {
|
|
126
129
|
if (ix.programAddress !== COMPUTE_BUDGET_PROGRAM_ADDRESS ||
|
|
127
130
|
ix.data?.[0] !== discriminator ||
|
|
131
|
+
ix.data.length !== size ||
|
|
128
132
|
ix.accounts?.length) {
|
|
129
133
|
throw invalid(`instruction ${index}: expected ${index === 0 ? "SetComputeUnitLimit" : "SetComputeUnitPrice"}`);
|
|
130
134
|
}
|
package/dist/test-rpc.d.ts
CHANGED
|
@@ -27,6 +27,13 @@ export interface MockRpcState {
|
|
|
27
27
|
}>;
|
|
28
28
|
/** Confirm every broadcast transaction immediately. */
|
|
29
29
|
autoConfirm: boolean;
|
|
30
|
+
/** Block height returned by getBlockHeight (blockhashes from getLatestBlockhash last to 1000). */
|
|
31
|
+
blockHeight: bigint;
|
|
32
|
+
/** Finalized slot from getEpochInfo, and the context slot of getSignatureStatuses answers. */
|
|
33
|
+
finalizedSlot: bigint;
|
|
34
|
+
statusSlot: bigint;
|
|
35
|
+
/** RPC methods that fail, to test an unavailable RPC. */
|
|
36
|
+
failing: Set<string>;
|
|
30
37
|
}
|
|
31
38
|
/** Base58 fee-payer signature of a base64 wire transaction. */
|
|
32
39
|
export declare const signatureOf: (wire: string) => import("@solana/kit").Signature;
|
package/dist/test-rpc.js
CHANGED
|
@@ -13,6 +13,10 @@ export function mockRpc() {
|
|
|
13
13
|
simulated: [],
|
|
14
14
|
transactions: new Map(),
|
|
15
15
|
autoConfirm: false,
|
|
16
|
+
blockHeight: 10n,
|
|
17
|
+
finalizedSlot: 1n,
|
|
18
|
+
statusSlot: 1n,
|
|
19
|
+
failing: new Set(),
|
|
16
20
|
};
|
|
17
21
|
const ok = (value) => ({ send: async () => value });
|
|
18
22
|
const rpc = {
|
|
@@ -58,8 +62,19 @@ export function mockRpc() {
|
|
|
58
62
|
return ok("5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7");
|
|
59
63
|
}
|
|
60
64
|
},
|
|
61
|
-
getSignatureStatuses: (signatures) => ok({
|
|
62
|
-
|
|
65
|
+
getSignatureStatuses: (signatures) => ok({
|
|
66
|
+
context: { slot: state.statusSlot },
|
|
67
|
+
value: signatures.map((s) => state.statuses.get(s) ?? null),
|
|
68
|
+
}),
|
|
69
|
+
getEpochInfo: () => ok({
|
|
70
|
+
absoluteSlot: state.finalizedSlot,
|
|
71
|
+
blockHeight: state.blockHeight,
|
|
72
|
+
epoch: 0n,
|
|
73
|
+
slotIndex: 0n,
|
|
74
|
+
slotsInEpoch: 432000n,
|
|
75
|
+
transactionCount: null,
|
|
76
|
+
}),
|
|
77
|
+
getBlockHeight: () => ok(state.blockHeight),
|
|
63
78
|
getTransaction: (signature) => {
|
|
64
79
|
const tx = state.transactions.get(signature);
|
|
65
80
|
return ok(tx
|
|
@@ -72,7 +87,17 @@ export function mockRpc() {
|
|
|
72
87
|
: null);
|
|
73
88
|
},
|
|
74
89
|
};
|
|
75
|
-
|
|
90
|
+
const failable = Object.fromEntries(Object.entries(rpc).map(([name, method]) => [
|
|
91
|
+
name,
|
|
92
|
+
(...args) => state.failing.has(name)
|
|
93
|
+
? {
|
|
94
|
+
send: async () => {
|
|
95
|
+
throw new Error(`${name}: RPC unavailable`);
|
|
96
|
+
},
|
|
97
|
+
}
|
|
98
|
+
: method(...args),
|
|
99
|
+
]));
|
|
100
|
+
return { rpc: failable, state };
|
|
76
101
|
}
|
|
77
102
|
export function putTokenAccount(state, address, owner, mint, amount) {
|
|
78
103
|
const data = getTokenEncoder().encode({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m2m-monster/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Core of m2m.monster: fees, quotes, and m2m-split transaction building and verification for x402 on Solana.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"agents",
|
|
11
11
|
"m2m-split"
|
|
12
12
|
],
|
|
13
|
-
"homepage": "https://
|
|
13
|
+
"homepage": "https://m2m.monster/llms.txt",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
16
|
"url": "git+https://github.com/m2mmonster/m2m-monster.git",
|