uvd-x402-sdk 2.86.0 → 2.88.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 +63 -0
- package/dist/backend/index.d.mts +1 -1
- package/dist/backend/index.d.ts +1 -1
- package/dist/backend/index.js +182 -17
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/index.mjs +181 -18
- package/dist/backend/index.mjs.map +1 -1
- package/dist/{index-De03nksW.d.mts → index-BMp3kzLX.d.mts} +315 -27
- package/dist/{index-4_LWWlyF.d.ts → index-Cc5JUhLY.d.ts} +315 -27
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +62 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +62 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/backend/index.ts +347 -27
- package/src/index.ts +2 -0
- package/src/lifecycle-auth.ts +209 -32
package/README.md
CHANGED
|
@@ -1142,6 +1142,69 @@ chain that supports EIP-7702 -- the payment stays where it was made.
|
|
|
1142
1142
|
|
|
1143
1143
|
Requires facilitator v1.93.0+ for the mainnets; base-sepolia since v1.74.0.
|
|
1144
1144
|
|
|
1145
|
+
### The same thing on Solana, without a delegate
|
|
1146
|
+
|
|
1147
|
+
Solana reaches the same place by a shorter road, so it is a **different pair of
|
|
1148
|
+
calls and a different network list**. The program's `give_feedback` instruction
|
|
1149
|
+
already declares account 0 as `[signer, writable] client (feedback author)`, and
|
|
1150
|
+
a Solana transaction carries several signatures natively: the rater signs as
|
|
1151
|
+
`client`, the facilitator co-signs as fee payer. Nothing is delegated because
|
|
1152
|
+
nothing has to be.
|
|
1153
|
+
|
|
1154
|
+
**`solana` never goes in `RELAYED_FEEDBACK_NETWORKS`.** That list drives
|
|
1155
|
+
`/feedback/evm/*` and names chains with a deployed `FeedbackDelegate`; a Solana
|
|
1156
|
+
rating sent there is a 400, and the entry would assert a delegate that was never
|
|
1157
|
+
deployed and is not missing. Use `SOLANA_FEEDBACK_NETWORKS` /
|
|
1158
|
+
`supportsSolanaFeedback()`.
|
|
1159
|
+
|
|
1160
|
+
```typescript
|
|
1161
|
+
import { Erc8004Client, supportsSolanaFeedback } from 'uvd-x402-sdk/backend';
|
|
1162
|
+
import { Transaction } from '@solana/web3.js';
|
|
1163
|
+
|
|
1164
|
+
const erc8004 = new Erc8004Client();
|
|
1165
|
+
|
|
1166
|
+
if (!supportsSolanaFeedback('solana')) {
|
|
1167
|
+
// fall back to submitFeedback(); the facilitator is the author there
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
const prep = await erc8004.prepareSolanaFeedback({
|
|
1171
|
+
x402Version: 1,
|
|
1172
|
+
network: 'solana',
|
|
1173
|
+
feedback: {
|
|
1174
|
+
agentId: '7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgHkv', // the agent asset
|
|
1175
|
+
rater: raterPubkey, // base58: who the chain will record as the author
|
|
1176
|
+
value: 87,
|
|
1177
|
+
valueDecimals: 0,
|
|
1178
|
+
score: 95, // WITHOUT THIS the rating counts for nothing
|
|
1179
|
+
tag1: 'quality',
|
|
1180
|
+
},
|
|
1181
|
+
});
|
|
1182
|
+
|
|
1183
|
+
// Sign the message as it came. Re-encoding it changes bytes the facilitator
|
|
1184
|
+
// will compare, and it refuses to co-sign anything it did not build. It is a
|
|
1185
|
+
// LEGACY transaction: `Transaction.from()`, not `VersionedTransaction`.
|
|
1186
|
+
const tx = Transaction.from(Buffer.from(prep.transaction!, 'base64'));
|
|
1187
|
+
tx.partialSign(raterKeypair); // ...or a wallet: await wallet.signTransaction(tx)
|
|
1188
|
+
|
|
1189
|
+
const result = await erc8004.submitSolanaFeedback({
|
|
1190
|
+
x402Version: 1,
|
|
1191
|
+
network: 'solana',
|
|
1192
|
+
feedback: { /* exactly what went to prepare, rater included */ },
|
|
1193
|
+
transaction: tx.serialize({ requireAllSignatures: false }).toString('base64'),
|
|
1194
|
+
});
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
`prep.feePayer` is the facilitator and `prep.rater` is the rater — that split is
|
|
1198
|
+
the whole point. Submit before `prep.lastValidBlockHeight`: past it the network
|
|
1199
|
+
drops the transaction, nothing is written and nothing is charged, and a resend
|
|
1200
|
+
needs a fresh `prepare()` because the blockhash the rater signed over is gone.
|
|
1201
|
+
|
|
1202
|
+
**Set `score`.** It is optional on the wire and the ATOM Engine ignores an
|
|
1203
|
+
unscored feedback: the transaction succeeds, the record lands on the agent, and
|
|
1204
|
+
reputation stays at zero (`had_impact=false`) — and it is not retroactive.
|
|
1205
|
+
|
|
1206
|
+
Available on `solana` and `solana-devnet`. Requires facilitator v2.16.0+.
|
|
1207
|
+
|
|
1145
1208
|
## `/accepts` Negotiation
|
|
1146
1209
|
|
|
1147
1210
|
Discover what the facilitator can settle before constructing payment authorizations. Used by Faremeter middleware and clients.
|
package/dist/backend/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import '../wallet-w7BnImDG.mjs';
|
|
2
2
|
import '../index-DOBhTF-j.mjs';
|
|
3
|
-
export { A as AMBIGUOUS_LEASE_REASONS,
|
|
3
|
+
export { A as AMBIGUOUS_LEASE_REASONS, ab as AdvancedAuthorizationResult, ac as AdvancedEscrowClient, ad as AdvancedEscrowClientOptions, ae as AdvancedEscrowContracts, af as AdvancedEscrowTaskTier, ag as AdvancedPaymentInfo, ah as AdvancedTransactionResult, ai as AgentId, aj as AgentIdentity, ak as AgentRegistration, al as AgentRegistrationFile, am as AgentService, an as AtomStats, ao as BASE_MAINNET_CONTRACTS, ap as BazaarClient, aq as BazaarClientOptions, ar as BazaarDiscoverOptions, as as BazaarDiscoverResponse, at as BazaarRegisterOptions, au as BazaarResource, av as CreateEscrowOptions, D as DEFAULT_FACILITATOR_RETRIES, a as DEFAULT_RETRY_AFTER_SECONDS, aw as DEPOSIT_LIMIT_USDC, ax as DiscoveryAccepts, ay as DiscoveryCuration, az as DiscoveryHealth, aA as DiscoveryHealthStatus, aB as DiscoveryListOptions, aC as DiscoveryPagination, aD as DiscoveryRegisterOptions, aE as DiscoveryResource, aF as DiscoveryResponse, aG as DiscoverySource, aH as DiscoveryStats, aI as DiscoveryTier, aJ as Dispute, aK as DisputeOutcome, aL as ERC8004_CONTRACTS, aM as ERC8004_EXTENSION_ID, aN as ESCROW_CONTRACTS, aO as ESCROW_TIMEOUT_MS, aP as Erc8004Client, aQ as Erc8004ClientOptions, aR as Erc8004LookupError, aS as Erc8004Network, aT as EscrowClient, aU as EscrowClientOptions, aV as EscrowPayment, aW as EscrowStateResponse, aX as EscrowStatus, F as FacilitatorClient, b as FacilitatorClientOptions, c as FacilitatorErrorInfo, d as FacilitatorFailureFields, e as FacilitatorFetchOptions, aY as FeedbackEntry, aZ as FeedbackParams, a_ as FeedbackRequest, a$ as FeedbackResponse, b0 as HEALTH_FILTERS, H as HonoMiddlewareOptions, b1 as IdentityByOwnerResponse, b2 as IdentityMetadataResponse, b3 as IdentityTotalSupplyResponse, b4 as LifecycleAuthOptions, M as MAX_RETRY_AFTER_SECONDS, b5 as MAX_SEARCH_LEN, b6 as MetadataEntryParam, b7 as OPERATOR_ABI, b8 as OPERATOR_ABI_CREATE3, b9 as PAYMENT_INFO_TYPEHASH, P as ParsedFacilitatorErrorBody, q as PaymentAcceptance, r as PaymentMiddlewareOptions, s as PaymentPayloadV2, ba as PaymentRequirementResolver, bb as PaymentRequirements, bc as PaymentRequirementsOptions, t as PaymentRequirementsV2, bd as PrepareRelayFeedbackRequest, be as PrepareRelayFeedbackResponse, bf as PrepareRelayResponseRequest, bg as PrepareSolanaFeedbackRequest, bh as PrepareSolanaFeedbackResponse, bi as ProofOfPayment, bj as RELAYED_FEEDBACK_NETWORKS, R as REPLAYABLE_LEASE_REASONS, bk as RefundRequest, bl as RefundStatus, bm as RegisterAgentRequest, bn as RegisterAgentResponse, bo as RegisterJobResponse, bp as RegisterJobStatus, bq as RegistrationPendingError, br as RelayAuthorizationParams, bs as ReputationResponse, bt as ReputationSummary, bu as RequestRefundOptions, u as ResourceInfoV2, S as SETTLEMENT_UNCONFIRMED, bv as SOLANA_FEEDBACK_NETWORKS, bw as SettleRequest, v as SettleRequestV2, bx as SettleResponse, by as SettleResponseWithProof, bz as SubmitRelayFeedbackRequest, bA as SubmitRelayResponseRequest, bB as SubmitSolanaFeedbackRequest, bC as TIER_FILTERS, bD as TIER_TIMINGS, bE as USDC_DOMAIN_NAME, bF as UnavailableBody, bG as UnavailableResponse, V as VerifiedPaymentState, bH as VerifyRequest, w as VerifyRequestV2, bI as VerifyResponse, W as WRITER_LEASE_REASONS, y as WriterLeaseReason, X as X402_CORS_HEADERS, z as X402_HEADER_NAMES, bJ as ZERO_ADDRESS, bK as buildErc8004PaymentRequirements, G as buildPaymentRequirements, I as buildSettleRequest, J as buildSettleRequestForVersion, K as buildSettleRequestV2, bL as buildUnavailableResponse, N as buildVerifyRequest, O as buildVerifyRequestForVersion, Q as buildVerifyRequestV2, bM as canRefundEscrow, bN as canReleaseEscrow, bO as carryFailureFields, T as create402Response, U as createHonoMiddleware, Y as createPaymentMiddleware, bP as epochToDate, bQ as escrowTimeRemaining, Z as extractPaymentFromHeaders, _ as facilitatorFetch, $ as getCorsHeaders, bR as getEscrowContractsByChainId, bS as getEscrowSupportedChainIds, bT as isAlive, a0 as isAmbiguousLeaseReason, bU as isEscrowExpired, bV as isEscrowSupportedOnChain, bW as isRegisterJobTerminal, a1 as isReplayableLeaseReason, a2 as isSettlementUnconfirmed, a4 as parseFacilitatorErrorBody, bX as parsePaymentHeader, a5 as parseRetryAfterSeconds, a6 as readFacilitatorError, a7 as resolveEnvelopeVersion, bY as supportsRelayedFeedback, bZ as supportsSolanaFeedback, a8 as toPaymentRequirementsV2, a9 as toResourceInfoV2, b_ as wireNetwork } from '../index-BMp3kzLX.mjs';
|
package/dist/backend/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import '../wallet-w7BnImDG.js';
|
|
2
2
|
import '../index-DOBhTF-j.js';
|
|
3
|
-
export { A as AMBIGUOUS_LEASE_REASONS,
|
|
3
|
+
export { A as AMBIGUOUS_LEASE_REASONS, ab as AdvancedAuthorizationResult, ac as AdvancedEscrowClient, ad as AdvancedEscrowClientOptions, ae as AdvancedEscrowContracts, af as AdvancedEscrowTaskTier, ag as AdvancedPaymentInfo, ah as AdvancedTransactionResult, ai as AgentId, aj as AgentIdentity, ak as AgentRegistration, al as AgentRegistrationFile, am as AgentService, an as AtomStats, ao as BASE_MAINNET_CONTRACTS, ap as BazaarClient, aq as BazaarClientOptions, ar as BazaarDiscoverOptions, as as BazaarDiscoverResponse, at as BazaarRegisterOptions, au as BazaarResource, av as CreateEscrowOptions, D as DEFAULT_FACILITATOR_RETRIES, a as DEFAULT_RETRY_AFTER_SECONDS, aw as DEPOSIT_LIMIT_USDC, ax as DiscoveryAccepts, ay as DiscoveryCuration, az as DiscoveryHealth, aA as DiscoveryHealthStatus, aB as DiscoveryListOptions, aC as DiscoveryPagination, aD as DiscoveryRegisterOptions, aE as DiscoveryResource, aF as DiscoveryResponse, aG as DiscoverySource, aH as DiscoveryStats, aI as DiscoveryTier, aJ as Dispute, aK as DisputeOutcome, aL as ERC8004_CONTRACTS, aM as ERC8004_EXTENSION_ID, aN as ESCROW_CONTRACTS, aO as ESCROW_TIMEOUT_MS, aP as Erc8004Client, aQ as Erc8004ClientOptions, aR as Erc8004LookupError, aS as Erc8004Network, aT as EscrowClient, aU as EscrowClientOptions, aV as EscrowPayment, aW as EscrowStateResponse, aX as EscrowStatus, F as FacilitatorClient, b as FacilitatorClientOptions, c as FacilitatorErrorInfo, d as FacilitatorFailureFields, e as FacilitatorFetchOptions, aY as FeedbackEntry, aZ as FeedbackParams, a_ as FeedbackRequest, a$ as FeedbackResponse, b0 as HEALTH_FILTERS, H as HonoMiddlewareOptions, b1 as IdentityByOwnerResponse, b2 as IdentityMetadataResponse, b3 as IdentityTotalSupplyResponse, b4 as LifecycleAuthOptions, M as MAX_RETRY_AFTER_SECONDS, b5 as MAX_SEARCH_LEN, b6 as MetadataEntryParam, b7 as OPERATOR_ABI, b8 as OPERATOR_ABI_CREATE3, b9 as PAYMENT_INFO_TYPEHASH, P as ParsedFacilitatorErrorBody, q as PaymentAcceptance, r as PaymentMiddlewareOptions, s as PaymentPayloadV2, ba as PaymentRequirementResolver, bb as PaymentRequirements, bc as PaymentRequirementsOptions, t as PaymentRequirementsV2, bd as PrepareRelayFeedbackRequest, be as PrepareRelayFeedbackResponse, bf as PrepareRelayResponseRequest, bg as PrepareSolanaFeedbackRequest, bh as PrepareSolanaFeedbackResponse, bi as ProofOfPayment, bj as RELAYED_FEEDBACK_NETWORKS, R as REPLAYABLE_LEASE_REASONS, bk as RefundRequest, bl as RefundStatus, bm as RegisterAgentRequest, bn as RegisterAgentResponse, bo as RegisterJobResponse, bp as RegisterJobStatus, bq as RegistrationPendingError, br as RelayAuthorizationParams, bs as ReputationResponse, bt as ReputationSummary, bu as RequestRefundOptions, u as ResourceInfoV2, S as SETTLEMENT_UNCONFIRMED, bv as SOLANA_FEEDBACK_NETWORKS, bw as SettleRequest, v as SettleRequestV2, bx as SettleResponse, by as SettleResponseWithProof, bz as SubmitRelayFeedbackRequest, bA as SubmitRelayResponseRequest, bB as SubmitSolanaFeedbackRequest, bC as TIER_FILTERS, bD as TIER_TIMINGS, bE as USDC_DOMAIN_NAME, bF as UnavailableBody, bG as UnavailableResponse, V as VerifiedPaymentState, bH as VerifyRequest, w as VerifyRequestV2, bI as VerifyResponse, W as WRITER_LEASE_REASONS, y as WriterLeaseReason, X as X402_CORS_HEADERS, z as X402_HEADER_NAMES, bJ as ZERO_ADDRESS, bK as buildErc8004PaymentRequirements, G as buildPaymentRequirements, I as buildSettleRequest, J as buildSettleRequestForVersion, K as buildSettleRequestV2, bL as buildUnavailableResponse, N as buildVerifyRequest, O as buildVerifyRequestForVersion, Q as buildVerifyRequestV2, bM as canRefundEscrow, bN as canReleaseEscrow, bO as carryFailureFields, T as create402Response, U as createHonoMiddleware, Y as createPaymentMiddleware, bP as epochToDate, bQ as escrowTimeRemaining, Z as extractPaymentFromHeaders, _ as facilitatorFetch, $ as getCorsHeaders, bR as getEscrowContractsByChainId, bS as getEscrowSupportedChainIds, bT as isAlive, a0 as isAmbiguousLeaseReason, bU as isEscrowExpired, bV as isEscrowSupportedOnChain, bW as isRegisterJobTerminal, a1 as isReplayableLeaseReason, a2 as isSettlementUnconfirmed, a4 as parseFacilitatorErrorBody, bX as parsePaymentHeader, a5 as parseRetryAfterSeconds, a6 as readFacilitatorError, a7 as resolveEnvelopeVersion, bY as supportsRelayedFeedback, bZ as supportsSolanaFeedback, a8 as toPaymentRequirementsV2, a9 as toResourceInfoV2, b_ as wireNetwork } from '../index-Cc5JUhLY.js';
|
package/dist/backend/index.js
CHANGED
|
@@ -1213,6 +1213,14 @@ function randomNonce() {
|
|
|
1213
1213
|
}
|
|
1214
1214
|
return ethers.ethers.hexlify(ethers.ethers.randomBytes(32));
|
|
1215
1215
|
}
|
|
1216
|
+
function resolveOrderTiming(params) {
|
|
1217
|
+
const nowSec = params.now === void 0 ? Math.floor(Date.now() / 1e3) : Math.floor(params.now);
|
|
1218
|
+
return {
|
|
1219
|
+
nowSec,
|
|
1220
|
+
deadline: params.deadline === void 0 ? nowSec + LIFECYCLE_DEFAULT_DEADLINE_SECS : Math.floor(params.deadline),
|
|
1221
|
+
nonce: params.nonce === void 0 ? randomNonce() : params.nonce
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1216
1224
|
function toUintString(value, field) {
|
|
1217
1225
|
let n;
|
|
1218
1226
|
try {
|
|
@@ -1226,7 +1234,8 @@ function toUintString(value, field) {
|
|
|
1226
1234
|
return n.toString();
|
|
1227
1235
|
}
|
|
1228
1236
|
function buildLifecycleTypedData(params) {
|
|
1229
|
-
const { action, paymentInfo, payer, amount, chainId
|
|
1237
|
+
const { action, paymentInfo, payer, amount, chainId } = params;
|
|
1238
|
+
const { deadline, nonce } = resolveOrderTiming(params);
|
|
1230
1239
|
if (!LIFECYCLE_ACTIONS.includes(action)) {
|
|
1231
1240
|
throw new X402Error(
|
|
1232
1241
|
`unknown lifecycle action ${String(action)}; the facilitator only signs ${LIFECYCLE_ACTIONS.join(", ")}`,
|
|
@@ -1285,10 +1294,8 @@ function buildLifecycleTypedData(params) {
|
|
|
1285
1294
|
};
|
|
1286
1295
|
}
|
|
1287
1296
|
async function buildLifecycleAuth(params) {
|
|
1288
|
-
const { wallet,
|
|
1289
|
-
const nowSec
|
|
1290
|
-
const dl = deadline === void 0 ? nowSec + LIFECYCLE_DEFAULT_DEADLINE_SECS : Math.floor(deadline);
|
|
1291
|
-
const nonceHex = nonce === void 0 ? randomNonce() : nonce;
|
|
1297
|
+
const { wallet, ...rest } = params;
|
|
1298
|
+
const { nowSec, deadline: dl, nonce: nonceHex } = resolveOrderTiming(params);
|
|
1292
1299
|
if (dl < nowSec) {
|
|
1293
1300
|
throw new X402Error(
|
|
1294
1301
|
`deadline ${dl} is in the past (now ${nowSec}): the facilitator discards it as \`expired\``,
|
|
@@ -3145,6 +3152,13 @@ var RELAYED_FEEDBACK_NETWORKS = [
|
|
|
3145
3152
|
function supportsRelayedFeedback(network) {
|
|
3146
3153
|
return RELAYED_FEEDBACK_NETWORKS.includes(wireNetwork(network));
|
|
3147
3154
|
}
|
|
3155
|
+
var SOLANA_FEEDBACK_NETWORKS = [
|
|
3156
|
+
"solana",
|
|
3157
|
+
"solana-devnet"
|
|
3158
|
+
];
|
|
3159
|
+
function supportsSolanaFeedback(network) {
|
|
3160
|
+
return SOLANA_FEEDBACK_NETWORKS.includes(wireNetwork(network));
|
|
3161
|
+
}
|
|
3148
3162
|
var Erc8004LookupError = class extends Error {
|
|
3149
3163
|
/** HTTP status returned by the facilitator */
|
|
3150
3164
|
status;
|
|
@@ -3625,6 +3639,135 @@ var Erc8004Client = class {
|
|
|
3625
3639
|
};
|
|
3626
3640
|
}
|
|
3627
3641
|
}
|
|
3642
|
+
/**
|
|
3643
|
+
* Ask the facilitator for the Solana transaction the rater must sign.
|
|
3644
|
+
*
|
|
3645
|
+
* Step 1 of the rater-authored rail on Solana. Writes nothing on-chain and
|
|
3646
|
+
* costs nothing: it resolves the programs and the agent asset, reads the
|
|
3647
|
+
* registry collection and a finalized blockhash, and hands back an UNSIGNED
|
|
3648
|
+
* transaction whose `client` account is the rater.
|
|
3649
|
+
*
|
|
3650
|
+
* Why this exists, and why it is not the EVM rail: the program's
|
|
3651
|
+
* `give_feedback` instruction declares account 0 as
|
|
3652
|
+
* `[signer, writable] client (feedback author / fee payer)`, and plain
|
|
3653
|
+
* `POST /feedback` puts the FACILITATOR's keypair there — so the chain
|
|
3654
|
+
* records the facilitator as the author of the rating. Solana carries several
|
|
3655
|
+
* signers per transaction natively, so the rater signs as `client` while the
|
|
3656
|
+
* facilitator stays the fee payer. **No delegation and no program change**,
|
|
3657
|
+
* which is why {@link SOLANA_FEEDBACK_NETWORKS} is its own list and `solana`
|
|
3658
|
+
* must never appear in {@link RELAYED_FEEDBACK_NETWORKS} — that one routes to
|
|
3659
|
+
* `/feedback/evm/*`, which answers 400 here.
|
|
3660
|
+
*
|
|
3661
|
+
* What to do with the answer:
|
|
3662
|
+
* 1. Deserialise `transaction` — base64 of the bincode-serialised **legacy**
|
|
3663
|
+
* transaction, which is `@solana/web3.js`'s `Transaction.from()`, not
|
|
3664
|
+
* `VersionedTransaction` — and add the RATER's ed25519 signature. Sign the
|
|
3665
|
+
* message as it came: re-encoding it changes bytes the facilitator will
|
|
3666
|
+
* compare. The fee payer's slot stays empty; `submit` fills it.
|
|
3667
|
+
* 2. Hand it back to {@link Erc8004Client.submitSolanaFeedback} with the SAME
|
|
3668
|
+
* feedback parameters, before `lastValidBlockHeight` passes.
|
|
3669
|
+
*
|
|
3670
|
+
* @param request - Network, rater pubkey and feedback parameters
|
|
3671
|
+
* @returns The unsigned transaction, the fee payer and the blockhash window
|
|
3672
|
+
*
|
|
3673
|
+
* @example
|
|
3674
|
+
* ```ts
|
|
3675
|
+
* import { Transaction } from '@solana/web3.js';
|
|
3676
|
+
*
|
|
3677
|
+
* const prep = await erc8004.prepareSolanaFeedback({
|
|
3678
|
+
* x402Version: 1,
|
|
3679
|
+
* network: 'solana',
|
|
3680
|
+
* feedback: {
|
|
3681
|
+
* agentId: '7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgHkv',
|
|
3682
|
+
* rater: raterPubkey, // base58: who the chain records as the author
|
|
3683
|
+
* value: 87,
|
|
3684
|
+
* score: 95, // without it the rating counts for nothing
|
|
3685
|
+
* tag1: 'quality',
|
|
3686
|
+
* },
|
|
3687
|
+
* });
|
|
3688
|
+
*
|
|
3689
|
+
* const tx = Transaction.from(Buffer.from(prep.transaction!, 'base64'));
|
|
3690
|
+
* tx.partialSign(raterKeypair);
|
|
3691
|
+
* ```
|
|
3692
|
+
*/
|
|
3693
|
+
async prepareSolanaFeedback(request) {
|
|
3694
|
+
const url = `${this.baseUrl}/feedback/solana/prepare`;
|
|
3695
|
+
const controller = new AbortController();
|
|
3696
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
3697
|
+
try {
|
|
3698
|
+
const response = await fetch(url, {
|
|
3699
|
+
method: "POST",
|
|
3700
|
+
headers: {
|
|
3701
|
+
"Content-Type": "application/json",
|
|
3702
|
+
"Accept": "application/json"
|
|
3703
|
+
},
|
|
3704
|
+
body: JSON.stringify({ ...request, network: wireNetwork(request.network) }),
|
|
3705
|
+
signal: controller.signal
|
|
3706
|
+
});
|
|
3707
|
+
clearTimeout(timeoutId);
|
|
3708
|
+
if (!response.ok) {
|
|
3709
|
+
const errorText = await response.text();
|
|
3710
|
+
return {
|
|
3711
|
+
success: false,
|
|
3712
|
+
error: `Facilitator error: ${response.status} - ${errorText}`,
|
|
3713
|
+
network: request.network
|
|
3714
|
+
};
|
|
3715
|
+
}
|
|
3716
|
+
return await response.json();
|
|
3717
|
+
} catch (error) {
|
|
3718
|
+
clearTimeout(timeoutId);
|
|
3719
|
+
return {
|
|
3720
|
+
success: false,
|
|
3721
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
3722
|
+
network: request.network
|
|
3723
|
+
};
|
|
3724
|
+
}
|
|
3725
|
+
}
|
|
3726
|
+
/**
|
|
3727
|
+
* Co-sign and send a rater-signed Solana feedback transaction.
|
|
3728
|
+
*
|
|
3729
|
+
* Step 2 of the rater-authored rail on Solana. What lands on-chain has the
|
|
3730
|
+
* RATER as `client`, so the agent's feedback lists the rater rather than the
|
|
3731
|
+
* facilitator — and only the rater can revoke it.
|
|
3732
|
+
*
|
|
3733
|
+
* Pass back the same feedback parameters {@link Erc8004Client.prepareSolanaFeedback}
|
|
3734
|
+
* was given. They are not redundant: the facilitator re-derives the message
|
|
3735
|
+
* from them plus the blockhash inside the submitted transaction, and refuses
|
|
3736
|
+
* to co-sign anything that is not byte-for-byte what it built
|
|
3737
|
+
* (`400 "submitted transaction does not match the one this facilitator built"`).
|
|
3738
|
+
* The rater's signature is verified BEFORE the facilitator adds its own, so a
|
|
3739
|
+
* transaction the network would reject never costs a fee.
|
|
3740
|
+
*
|
|
3741
|
+
* @param request - Feedback parameters plus the rater-signed transaction
|
|
3742
|
+
* @returns Feedback response with the transaction signature
|
|
3743
|
+
*/
|
|
3744
|
+
async submitSolanaFeedback(request) {
|
|
3745
|
+
const url = `${this.baseUrl}/feedback/solana/submit`;
|
|
3746
|
+
try {
|
|
3747
|
+
const { response, error } = await this.writeJson(url, {
|
|
3748
|
+
...request,
|
|
3749
|
+
network: wireNetwork(request.network)
|
|
3750
|
+
});
|
|
3751
|
+
if (error) {
|
|
3752
|
+
return {
|
|
3753
|
+
success: false,
|
|
3754
|
+
error: error.error,
|
|
3755
|
+
network: request.network,
|
|
3756
|
+
...failureFields(error)
|
|
3757
|
+
};
|
|
3758
|
+
}
|
|
3759
|
+
return await response.json();
|
|
3760
|
+
} catch (error) {
|
|
3761
|
+
return {
|
|
3762
|
+
success: false,
|
|
3763
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
3764
|
+
network: request.network,
|
|
3765
|
+
retryable: true,
|
|
3766
|
+
safeToReplay: false,
|
|
3767
|
+
retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS
|
|
3768
|
+
};
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3628
3771
|
/**
|
|
3629
3772
|
* Revoke previously submitted feedback
|
|
3630
3773
|
*
|
|
@@ -4259,6 +4402,25 @@ var TIER_TIMINGS = {
|
|
|
4259
4402
|
premium: { pre: 14400, auth: 172800, refund: 1209600 },
|
|
4260
4403
|
enterprise: { pre: 86400, auth: 604800, refund: 2592e3 }
|
|
4261
4404
|
};
|
|
4405
|
+
async function resolveLifecycleAuth(action, options, order) {
|
|
4406
|
+
if (options?.lifecycleSigner && options?.lifecycleAuth) {
|
|
4407
|
+
throw new X402Error(
|
|
4408
|
+
"lifecycleSigner and lifecycleAuth are mutually exclusive: the first signs an order here, the second was already signed elsewhere. Passing both means two different orders exist and only one can travel.",
|
|
4409
|
+
"INVALID_CONFIG"
|
|
4410
|
+
);
|
|
4411
|
+
}
|
|
4412
|
+
if (options?.lifecycleAuth) return options.lifecycleAuth;
|
|
4413
|
+
if (!options?.lifecycleSigner) return void 0;
|
|
4414
|
+
return buildLifecycleAuth({
|
|
4415
|
+
action,
|
|
4416
|
+
paymentInfo: order.paymentInfo,
|
|
4417
|
+
payer: order.payer,
|
|
4418
|
+
amount: order.amount,
|
|
4419
|
+
chainId: order.chainId,
|
|
4420
|
+
wallet: options.lifecycleSigner,
|
|
4421
|
+
deadline: options.lifecycleDeadline
|
|
4422
|
+
});
|
|
4423
|
+
}
|
|
4262
4424
|
var OPERATOR_ABI = [
|
|
4263
4425
|
"function release(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount)",
|
|
4264
4426
|
"function refundInEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint120 amount)",
|
|
@@ -4669,6 +4831,13 @@ var AdvancedEscrowClient = class {
|
|
|
4669
4831
|
* lifecycleSigner: payerWallet, // EnvKeyAdapter, OWS, wagmiLifecycleSigner(...)
|
|
4670
4832
|
* });
|
|
4671
4833
|
* ```
|
|
4834
|
+
*
|
|
4835
|
+
* @example Transporting an order the publisher signed in their browser
|
|
4836
|
+
* ```typescript
|
|
4837
|
+
* // The browser sent back a signature over a document THIS backend built.
|
|
4838
|
+
* const lifecycleAuth = lifecycleAuthFromSignature(typedData, signature, payer);
|
|
4839
|
+
* await client.releaseViaFacilitator(pi, amount, { lifecycleAuth });
|
|
4840
|
+
* ```
|
|
4672
4841
|
*/
|
|
4673
4842
|
async releaseViaFacilitator(paymentInfo, amount, options) {
|
|
4674
4843
|
if (!this.payerAddress) await this.init();
|
|
@@ -4687,15 +4856,12 @@ var AdvancedEscrowClient = class {
|
|
|
4687
4856
|
salt: paymentInfo.salt
|
|
4688
4857
|
};
|
|
4689
4858
|
const releaseAmount = amount || paymentInfo.maxAmount;
|
|
4690
|
-
const lifecycleAuth =
|
|
4691
|
-
action: "release",
|
|
4859
|
+
const lifecycleAuth = await resolveLifecycleAuth("release", options, {
|
|
4692
4860
|
paymentInfo: wirePaymentInfo,
|
|
4693
4861
|
payer: this.payerAddress,
|
|
4694
4862
|
amount: releaseAmount,
|
|
4695
|
-
chainId: this.chainId
|
|
4696
|
-
|
|
4697
|
-
deadline: options.lifecycleDeadline
|
|
4698
|
-
}) : void 0;
|
|
4863
|
+
chainId: this.chainId
|
|
4864
|
+
});
|
|
4699
4865
|
const payload = {
|
|
4700
4866
|
x402Version: 2,
|
|
4701
4867
|
scheme: "escrow",
|
|
@@ -4824,15 +4990,12 @@ var AdvancedEscrowClient = class {
|
|
|
4824
4990
|
salt: paymentInfo.salt
|
|
4825
4991
|
};
|
|
4826
4992
|
const refundAmount = amount || paymentInfo.maxAmount;
|
|
4827
|
-
const lifecycleAuth =
|
|
4828
|
-
action: "refundInEscrow",
|
|
4993
|
+
const lifecycleAuth = await resolveLifecycleAuth("refundInEscrow", options, {
|
|
4829
4994
|
paymentInfo: wirePaymentInfo,
|
|
4830
4995
|
payer: this.payerAddress,
|
|
4831
4996
|
amount: refundAmount,
|
|
4832
|
-
chainId: this.chainId
|
|
4833
|
-
|
|
4834
|
-
deadline: options.lifecycleDeadline
|
|
4835
|
-
}) : void 0;
|
|
4997
|
+
chainId: this.chainId
|
|
4998
|
+
});
|
|
4836
4999
|
const payload = {
|
|
4837
5000
|
x402Version: 2,
|
|
4838
5001
|
scheme: "escrow",
|
|
@@ -5128,6 +5291,7 @@ exports.RELAYED_FEEDBACK_NETWORKS = RELAYED_FEEDBACK_NETWORKS;
|
|
|
5128
5291
|
exports.REPLAYABLE_LEASE_REASONS = REPLAYABLE_LEASE_REASONS;
|
|
5129
5292
|
exports.RegistrationPendingError = RegistrationPendingError;
|
|
5130
5293
|
exports.SETTLEMENT_UNCONFIRMED = SETTLEMENT_UNCONFIRMED;
|
|
5294
|
+
exports.SOLANA_FEEDBACK_NETWORKS = SOLANA_FEEDBACK_NETWORKS;
|
|
5131
5295
|
exports.TIER_FILTERS = TIER_FILTERS;
|
|
5132
5296
|
exports.TIER_TIMINGS = TIER_TIMINGS;
|
|
5133
5297
|
exports.USDC_DOMAIN_NAME = USDC_DOMAIN_NAME;
|
|
@@ -5170,6 +5334,7 @@ exports.parseRetryAfterSeconds = parseRetryAfterSeconds;
|
|
|
5170
5334
|
exports.readFacilitatorError = readFacilitatorError;
|
|
5171
5335
|
exports.resolveEnvelopeVersion = resolveEnvelopeVersion;
|
|
5172
5336
|
exports.supportsRelayedFeedback = supportsRelayedFeedback;
|
|
5337
|
+
exports.supportsSolanaFeedback = supportsSolanaFeedback;
|
|
5173
5338
|
exports.toPaymentRequirementsV2 = toPaymentRequirementsV2;
|
|
5174
5339
|
exports.toResourceInfoV2 = toResourceInfoV2;
|
|
5175
5340
|
exports.wireNetwork = wireNetwork;
|