primcli 1.6.1 → 1.7.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/dist/oclif/index.js +95 -27
- package/package.json +1 -1
package/dist/oclif/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import process$1 from "node:process";
|
|
|
7
7
|
import { createInterface } from "node:readline/promises";
|
|
8
8
|
import { hostname } from "node:os";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
|
-
import { concat, hexToBytes, keccak256, stringToBytes } from "viem";
|
|
10
|
+
import { concat, getAddress, hexToBytes, keccak256, stringToBytes } from "viem";
|
|
11
11
|
import { privateKeyToAccount } from "viem/accounts";
|
|
12
12
|
//#region \0rolldown/runtime.js
|
|
13
13
|
var __defProp = Object.defineProperty;
|
|
@@ -21020,8 +21020,8 @@ const PRIMITIVE_TEAM_AUTHOR = {
|
|
|
21020
21020
|
name: "Primitive Team",
|
|
21021
21021
|
url: "https://primitive.dev"
|
|
21022
21022
|
};
|
|
21023
|
-
const SDK_VERSION_RANGE = "^1.
|
|
21024
|
-
const CLI_VERSION_RANGE = "^1.
|
|
21023
|
+
const SDK_VERSION_RANGE = "^1.7.0";
|
|
21024
|
+
const CLI_VERSION_RANGE = "^1.7.0";
|
|
21025
21025
|
const ESBUILD_VERSION_RANGE = "^0.27.0";
|
|
21026
21026
|
function renderHandler() {
|
|
21027
21027
|
return `// env.PRIMITIVE_API_KEY, env.PRIMITIVE_WEBHOOK_SECRET, and
|
|
@@ -24528,12 +24528,68 @@ function toPaymentPayload(network, auth, signature) {
|
|
|
24528
24528
|
}
|
|
24529
24529
|
};
|
|
24530
24530
|
}
|
|
24531
|
+
/**
|
|
24532
|
+
* Compute the EIP-3009 validity window for a payment. `validBefore` is the
|
|
24533
|
+
* value that governs on-chain validity, so it MUST cover the challenge's
|
|
24534
|
+
* `expires_at` plus a settlement margin; `validAfter` is set generously in the
|
|
24535
|
+
* past for clock skew. The total window is hard-capped at `maxWindowSec` so
|
|
24536
|
+
* neither a far-future `challengeExpiresAtSec` nor a widened margin can produce
|
|
24537
|
+
* a window the platform verifier would later reject.
|
|
24538
|
+
*/
|
|
24539
|
+
function computePaymentValidityWindow(params) {
|
|
24540
|
+
const margin = params.settlementMarginSec ?? 300;
|
|
24541
|
+
const skew = params.clockSkewSec ?? 300;
|
|
24542
|
+
const validBefore = BigInt(params.challengeExpiresAtSec + margin);
|
|
24543
|
+
const validAfter = BigInt(params.nowSec - skew);
|
|
24544
|
+
if (validBefore <= validAfter) throw new Error("invalid validity window: validBefore must be after validAfter (challenge already expired?)");
|
|
24545
|
+
const maxWindow = BigInt(params.maxWindowSec ?? 86400);
|
|
24546
|
+
if (validBefore - validAfter > maxWindow) throw new Error(`invalid validity window: total window exceeds the ${maxWindow}s cap (challenge expiry too far out?)`);
|
|
24547
|
+
return {
|
|
24548
|
+
validAfter,
|
|
24549
|
+
validBefore
|
|
24550
|
+
};
|
|
24551
|
+
}
|
|
24552
|
+
/**
|
|
24553
|
+
* The interaction-aware signer: derive the bound nonce, assemble the
|
|
24554
|
+
* authorization, and sign it. This is the one piece a stock x402 signer cannot
|
|
24555
|
+
* do (it generates the nonce internally with no injection point), so the payer
|
|
24556
|
+
* side needs this Primitive-provided helper. The key never leaves the caller.
|
|
24557
|
+
*/
|
|
24558
|
+
async function signInteractionPayment(params) {
|
|
24559
|
+
const authorization = {
|
|
24560
|
+
from: getAddress(params.payer),
|
|
24561
|
+
to: getAddress(params.payTo),
|
|
24562
|
+
value: params.amount,
|
|
24563
|
+
validAfter: params.validAfter,
|
|
24564
|
+
validBefore: params.validBefore,
|
|
24565
|
+
nonce: deriveEip3009Nonce(params.nonceBinding)
|
|
24566
|
+
};
|
|
24567
|
+
return {
|
|
24568
|
+
authorization,
|
|
24569
|
+
signature: await params.sign(transferWithAuthorizationTypedData(params.domain, authorization))
|
|
24570
|
+
};
|
|
24571
|
+
}
|
|
24572
|
+
/** The authorization nonce is 32 bytes rendered as a 0x-prefixed 64-char hex string. */
|
|
24573
|
+
const NONCE_HEX_RE = /^0x[0-9a-fA-F]{64}$/;
|
|
24574
|
+
/** A shape-valid EIP signature is 65 bytes (r,s,v) rendered as 130 hex chars. */
|
|
24575
|
+
const SIGNATURE_HEX_RE = /^0x[0-9a-fA-F]{130}$/;
|
|
24576
|
+
/**
|
|
24577
|
+
* Assemble (and validate) the exact-EVM x402 wire payload from an
|
|
24578
|
+
* interaction-bound, locally-signed authorization. The numeric authorization
|
|
24579
|
+
* fields are decimal strings in the wire schema, so the bigints are stringified
|
|
24580
|
+
* here; the nonce passes through as hex. Validation rejects a malformed nonce or
|
|
24581
|
+
* signature loudly rather than emitting a payload the platform will reject.
|
|
24582
|
+
*/
|
|
24583
|
+
function buildExactEvmPaymentPayload(params) {
|
|
24584
|
+
if (params.network !== "base" && params.network !== "base-sepolia") throw new Error(`buildExactEvmPaymentPayload: unsupported network ${params.network}`);
|
|
24585
|
+
if (!SIGNATURE_HEX_RE.test(params.signature)) throw new Error("buildExactEvmPaymentPayload: signature must be a 0x-prefixed 65-byte (130 hex char) EIP signature");
|
|
24586
|
+
if (!NONCE_HEX_RE.test(params.authorization.nonce)) throw new Error("buildExactEvmPaymentPayload: authorization.nonce must be a 0x-prefixed 32-byte (64 hex char) value");
|
|
24587
|
+
return toPaymentPayload(params.network, params.authorization, params.signature);
|
|
24588
|
+
}
|
|
24531
24589
|
const CHAIN_IDS = {
|
|
24532
24590
|
"base-sepolia": 84532,
|
|
24533
24591
|
base: 8453
|
|
24534
24592
|
};
|
|
24535
|
-
const CLOCK_SKEW_SEC = 300;
|
|
24536
|
-
const SETTLEMENT_MARGIN_SEC = 300;
|
|
24537
24593
|
const DEFAULT_BASE_URL = "https://api.primitive.dev";
|
|
24538
24594
|
const CHARGE_INPUT_KEYS = {
|
|
24539
24595
|
amount: true,
|
|
@@ -24583,7 +24639,7 @@ function validateChallenge(c) {
|
|
|
24583
24639
|
if (!nb?.interaction_id || !nb.challenge_step_id || !nb.challenge_nonce) bad("nonce_binding");
|
|
24584
24640
|
const pr = c.payment_requirements;
|
|
24585
24641
|
if (!pr) bad("payment_requirements");
|
|
24586
|
-
if (
|
|
24642
|
+
if (!/^[1-9][0-9]{0,38}$/.test(pr.maxAmountRequired ?? "")) bad("payment_requirements.maxAmountRequired (expected a positive integer string in token base units)");
|
|
24587
24643
|
if (!/^0x[0-9a-fA-F]{40}$/.test(pr.payTo ?? "")) bad("payment_requirements.payTo (expected a 0x address)");
|
|
24588
24644
|
if (!/^0x[0-9a-fA-F]{40}$/.test(pr.asset ?? "")) bad("payment_requirements.asset (expected a 0x address)");
|
|
24589
24645
|
if (!pr.extra?.name || !pr.extra.version) bad("payment_requirements.extra (name/version)");
|
|
@@ -24658,33 +24714,45 @@ var X402Client = class {
|
|
|
24658
24714
|
const pr = challenge.payment_requirements;
|
|
24659
24715
|
if (pr.network !== challenge.network) throw new X402Error(`challenge network mismatch: ${challenge.network} vs payment_requirements ${pr.network}`, 0);
|
|
24660
24716
|
if (pr.scheme !== "exact") throw new X402Error(`unsupported payment scheme: ${pr.scheme}`, 0);
|
|
24661
|
-
const nonce = deriveEip3009Nonce({
|
|
24662
|
-
interactionId: challenge.nonce_binding.interaction_id,
|
|
24663
|
-
challengeStepId: challenge.nonce_binding.challenge_step_id,
|
|
24664
|
-
challengeNonce: challenge.nonce_binding.challenge_nonce
|
|
24665
|
-
});
|
|
24666
24717
|
const nowSec = Math.floor(Date.now() / 1e3);
|
|
24667
24718
|
const expiresAtMs = Date.parse(challenge.expires_at);
|
|
24668
24719
|
if (Number.isNaN(expiresAtMs)) throw new X402Error(`challenge has an invalid expires_at: ${challenge.expires_at}`, 0);
|
|
24669
24720
|
const expiresAtSec = Math.floor(expiresAtMs / 1e3);
|
|
24670
24721
|
if (expiresAtSec <= nowSec) throw new X402Error(`challenge has already expired (expires_at ${challenge.expires_at}); not signing`, 0);
|
|
24671
|
-
|
|
24672
|
-
|
|
24673
|
-
|
|
24674
|
-
|
|
24675
|
-
|
|
24676
|
-
|
|
24722
|
+
let validAfter;
|
|
24723
|
+
let validBefore;
|
|
24724
|
+
try {
|
|
24725
|
+
({validAfter, validBefore} = computePaymentValidityWindow({
|
|
24726
|
+
challengeExpiresAtSec: expiresAtSec,
|
|
24727
|
+
nowSec
|
|
24728
|
+
}));
|
|
24729
|
+
} catch (cause) {
|
|
24730
|
+
throw new X402Error(cause instanceof Error ? cause.message : String(cause), 0, void 0, { cause });
|
|
24731
|
+
}
|
|
24732
|
+
const { authorization, signature } = await signInteractionPayment({
|
|
24733
|
+
sign: (typedData) => options.signer.signTypedData(typedData),
|
|
24734
|
+
payer: options.signer.address,
|
|
24735
|
+
domain: {
|
|
24736
|
+
name: pr.extra.name,
|
|
24737
|
+
version: pr.extra.version,
|
|
24738
|
+
chainId,
|
|
24739
|
+
verifyingContract: pr.asset
|
|
24740
|
+
},
|
|
24741
|
+
payTo: pr.payTo,
|
|
24742
|
+
amount: BigInt(pr.maxAmountRequired),
|
|
24743
|
+
nonceBinding: {
|
|
24744
|
+
interactionId: challenge.nonce_binding.interaction_id,
|
|
24745
|
+
challengeStepId: challenge.nonce_binding.challenge_step_id,
|
|
24746
|
+
challengeNonce: challenge.nonce_binding.challenge_nonce
|
|
24747
|
+
},
|
|
24677
24748
|
validAfter,
|
|
24678
|
-
validBefore
|
|
24679
|
-
|
|
24680
|
-
}
|
|
24681
|
-
|
|
24682
|
-
|
|
24683
|
-
|
|
24684
|
-
|
|
24685
|
-
verifyingContract: pr.asset
|
|
24686
|
-
}, auth));
|
|
24687
|
-
return this.#request("POST", `/v1/x402/challenges/${challenge.id}/pay`, { payment: toPaymentPayload(challenge.network, auth, signature) });
|
|
24749
|
+
validBefore
|
|
24750
|
+
});
|
|
24751
|
+
return this.#request("POST", `/v1/x402/challenges/${challenge.id}/pay`, { payment: buildExactEvmPaymentPayload({
|
|
24752
|
+
network: challenge.network,
|
|
24753
|
+
authorization,
|
|
24754
|
+
signature
|
|
24755
|
+
}) });
|
|
24688
24756
|
}
|
|
24689
24757
|
/** Fetch a challenge by id (scoped to the challenger org that created it). */
|
|
24690
24758
|
async getChallenge(id) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "primcli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Official Primitive CLI: deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal. Wraps the @primitivedotdev/sdk runtime client with one-shot commands.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|