uvd-x402-sdk 2.11.1 → 2.13.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/adapters/index.d.mts +1 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/index.mjs.map +1 -1
- package/dist/backend/index.d.mts +1 -1
- package/dist/backend/index.d.ts +1 -1
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/index.mjs.map +1 -1
- package/dist/{index-C60c_e5z.d.mts → index-C6Vxnneo.d.mts} +1 -1
- package/dist/{index-VIOUicmO.d.ts → index-DmJGKD9r.d.ts} +1 -1
- package/dist/{index-D-dO_FoP.d.mts → index-fIhvHqCQ.d.mts} +18 -22
- package/dist/{index-D-dO_FoP.d.ts → index-fIhvHqCQ.d.ts} +18 -22
- package/dist/index.d.mts +56 -2
- package/dist/index.d.ts +56 -2
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +58 -1
- package/dist/index.mjs.map +1 -1
- package/dist/providers/algorand/index.d.mts +11 -5
- package/dist/providers/algorand/index.d.ts +11 -5
- package/dist/providers/algorand/index.js +142 -27
- package/dist/providers/algorand/index.js.map +1 -1
- package/dist/providers/algorand/index.mjs +142 -27
- package/dist/providers/algorand/index.mjs.map +1 -1
- package/dist/providers/evm/index.d.mts +1 -1
- package/dist/providers/evm/index.d.ts +1 -1
- package/dist/providers/evm/index.js.map +1 -1
- package/dist/providers/evm/index.mjs.map +1 -1
- package/dist/providers/near/index.d.mts +1 -1
- package/dist/providers/near/index.d.ts +1 -1
- package/dist/providers/near/index.js.map +1 -1
- package/dist/providers/near/index.mjs.map +1 -1
- package/dist/providers/solana/index.d.mts +1 -1
- package/dist/providers/solana/index.d.ts +1 -1
- package/dist/providers/solana/index.js.map +1 -1
- package/dist/providers/solana/index.mjs.map +1 -1
- package/dist/providers/stellar/index.d.mts +1 -1
- package/dist/providers/stellar/index.d.ts +1 -1
- package/dist/providers/stellar/index.js.map +1 -1
- package/dist/providers/stellar/index.mjs.map +1 -1
- package/dist/react/index.d.mts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs.map +1 -1
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/facilitator.ts +106 -0
- package/src/index.ts +4 -0
- package/src/providers/algorand/index.ts +122 -32
- package/src/types/index.ts +18 -22
|
@@ -674,6 +674,50 @@ function chainToCAIP2(chainName) {
|
|
|
674
674
|
return chainName;
|
|
675
675
|
}
|
|
676
676
|
|
|
677
|
+
// src/facilitator.ts
|
|
678
|
+
var FACILITATOR_ADDRESSES = {
|
|
679
|
+
/**
|
|
680
|
+
* Solana facilitator address (fee payer)
|
|
681
|
+
* Used for: Paying transaction fees on Solana
|
|
682
|
+
*/
|
|
683
|
+
solana: "F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq",
|
|
684
|
+
/**
|
|
685
|
+
* Algorand facilitator address (fee payer)
|
|
686
|
+
* Used for: Signing Transaction 0 (fee tx) in atomic groups
|
|
687
|
+
* Note: This is derived from the facilitator's Algorand mnemonic
|
|
688
|
+
*/
|
|
689
|
+
algorand: "SXHRBXS22SKKXHXK44DTQMWN2SXK3SFJWBDAQZGF4DRPW7PNFAUM2GYFAQ",
|
|
690
|
+
/**
|
|
691
|
+
* Algorand testnet facilitator address
|
|
692
|
+
*/
|
|
693
|
+
"algorand-testnet": "SXHRBXS22SKKXHXK44DTQMWN2SXK3SFJWBDAQZGF4DRPW7PNFAUM2GYFAQ",
|
|
694
|
+
/**
|
|
695
|
+
* EVM facilitator address
|
|
696
|
+
* Used for: Submitting EIP-3009 transferWithAuthorization transactions
|
|
697
|
+
* Note: Same address across all EVM chains
|
|
698
|
+
*/
|
|
699
|
+
evm: "0x7c5F3AdB0C7775968Bc7e7cF61b27fECf2e2b500",
|
|
700
|
+
/**
|
|
701
|
+
* Stellar facilitator address
|
|
702
|
+
* Used for: Signing soroban authorization entries
|
|
703
|
+
*/
|
|
704
|
+
stellar: "GDUTDNV53WQPOB2JUZPO6SXH4LVT7CJSLCMLFQ7W4CNAXGIX7XYMCNP2",
|
|
705
|
+
/**
|
|
706
|
+
* NEAR facilitator address
|
|
707
|
+
* Used for: Relaying meta-transactions
|
|
708
|
+
*/
|
|
709
|
+
near: "uvd-facilitator.near"
|
|
710
|
+
};
|
|
711
|
+
function getFacilitatorAddress(chainName, networkType) {
|
|
712
|
+
const exactMatch = FACILITATOR_ADDRESSES[chainName];
|
|
713
|
+
if (exactMatch) {
|
|
714
|
+
return exactMatch;
|
|
715
|
+
}
|
|
716
|
+
{
|
|
717
|
+
return FACILITATOR_ADDRESSES.algorand;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
677
721
|
// src/providers/algorand/index.ts
|
|
678
722
|
function uint8ArrayToBase64(bytes) {
|
|
679
723
|
let binary = "";
|
|
@@ -877,11 +921,13 @@ var AlgorandProvider = class {
|
|
|
877
921
|
}
|
|
878
922
|
}
|
|
879
923
|
/**
|
|
880
|
-
* Create Algorand
|
|
924
|
+
* Create Algorand atomic group payment (GoPlausible x402-avm spec)
|
|
925
|
+
*
|
|
926
|
+
* Transaction structure (atomic group):
|
|
927
|
+
* - Transaction 0: Fee payment (UNSIGNED) - facilitator -> facilitator, covers all fees
|
|
928
|
+
* - Transaction 1: ASA transfer (SIGNED) - client -> merchant
|
|
881
929
|
*
|
|
882
|
-
*
|
|
883
|
-
* 1. ASA Transfer from user to recipient
|
|
884
|
-
* 2. Facilitator pays transaction fees
|
|
930
|
+
* The facilitator signs transaction 0 and submits the complete atomic group.
|
|
885
931
|
*/
|
|
886
932
|
async signPayment(paymentInfo, chainConfig) {
|
|
887
933
|
await loadAlgorandDeps();
|
|
@@ -894,40 +940,86 @@ var AlgorandProvider = class {
|
|
|
894
940
|
const algodClient = await this.getAlgodClient(chainConfig);
|
|
895
941
|
const recipient = paymentInfo.recipients?.algorand || paymentInfo.recipient;
|
|
896
942
|
const assetId = parseInt(chainConfig.usdc.address, 10);
|
|
943
|
+
const chainName = chainConfig?.name || "algorand";
|
|
944
|
+
const facilitatorAddress = paymentInfo.facilitator || getFacilitatorAddress(chainName);
|
|
945
|
+
if (!facilitatorAddress) {
|
|
946
|
+
throw new X402Error(
|
|
947
|
+
"Facilitator address not configured for Algorand",
|
|
948
|
+
"PAYMENT_FAILED"
|
|
949
|
+
);
|
|
950
|
+
}
|
|
897
951
|
const amount = Math.floor(parseFloat(paymentInfo.amount) * 1e6);
|
|
898
952
|
try {
|
|
899
953
|
const suggestedParams = await algodClient.getTransactionParams().do();
|
|
900
|
-
const
|
|
954
|
+
const feeTxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
|
|
955
|
+
sender: facilitatorAddress,
|
|
956
|
+
receiver: facilitatorAddress,
|
|
957
|
+
// self-transfer
|
|
958
|
+
amount: 0,
|
|
959
|
+
suggestedParams: {
|
|
960
|
+
...suggestedParams,
|
|
961
|
+
fee: 2e3,
|
|
962
|
+
// Covers both transactions (1000 each)
|
|
963
|
+
flatFee: true
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
const paymentTxn = algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
901
967
|
sender: this.address,
|
|
902
968
|
receiver: recipient,
|
|
903
969
|
amount: BigInt(amount),
|
|
904
970
|
assetIndex: assetId,
|
|
905
|
-
suggestedParams
|
|
971
|
+
suggestedParams: {
|
|
972
|
+
...suggestedParams,
|
|
973
|
+
fee: 0,
|
|
974
|
+
// Fee paid by transaction 0
|
|
975
|
+
flatFee: true
|
|
976
|
+
},
|
|
906
977
|
note: new TextEncoder().encode("x402 payment via uvd-x402-sdk")
|
|
907
978
|
});
|
|
908
|
-
|
|
979
|
+
const txnGroup = algosdk.assignGroupID([feeTxn, paymentTxn]);
|
|
980
|
+
const unsignedFeeTxnBytes = algosdk.encodeUnsignedTransaction(txnGroup[0]);
|
|
981
|
+
const unsignedFeeTxnBase64 = uint8ArrayToBase64(unsignedFeeTxnBytes);
|
|
982
|
+
let signedPaymentTxnBytes;
|
|
909
983
|
if (this.walletType === "lute" && this.luteWallet) {
|
|
910
|
-
const
|
|
911
|
-
const
|
|
912
|
-
|
|
984
|
+
const feeTxnBase64 = uint8ArrayToBase64(txnGroup[0].toByte());
|
|
985
|
+
const paymentTxnBase64 = uint8ArrayToBase64(txnGroup[1].toByte());
|
|
986
|
+
const signedTxns = await this.luteWallet.signTxns([
|
|
987
|
+
{ txn: feeTxnBase64, signers: [] },
|
|
988
|
+
// Don't sign - facilitator will
|
|
989
|
+
{ txn: paymentTxnBase64 }
|
|
990
|
+
// Sign this one
|
|
991
|
+
]);
|
|
992
|
+
if (!signedTxns || signedTxns.length < 2 || !signedTxns[1]) {
|
|
913
993
|
throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
|
|
914
994
|
}
|
|
915
|
-
|
|
995
|
+
const signedResult = signedTxns[1];
|
|
996
|
+
signedPaymentTxnBytes = this.decodeSignedTxn(signedResult);
|
|
916
997
|
} else if (this.walletType === "pera" && this.peraWallet) {
|
|
917
|
-
const signedTxns = await this.peraWallet.signTransaction([
|
|
918
|
-
|
|
998
|
+
const signedTxns = await this.peraWallet.signTransaction([
|
|
999
|
+
[
|
|
1000
|
+
{ txn: txnGroup[0], signers: [] },
|
|
1001
|
+
// Don't sign - facilitator will
|
|
1002
|
+
{ txn: txnGroup[1] }
|
|
1003
|
+
// Sign this one
|
|
1004
|
+
]
|
|
1005
|
+
]);
|
|
1006
|
+
if (!signedTxns || signedTxns.length < 2 || !signedTxns[1]) {
|
|
919
1007
|
throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
|
|
920
1008
|
}
|
|
921
|
-
|
|
1009
|
+
signedPaymentTxnBytes = signedTxns[1];
|
|
922
1010
|
} else {
|
|
923
1011
|
throw new X402Error("No wallet available for signing", "WALLET_NOT_CONNECTED");
|
|
924
1012
|
}
|
|
1013
|
+
const signedPaymentTxnBase64 = uint8ArrayToBase64(signedPaymentTxnBytes);
|
|
925
1014
|
const payload = {
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
1015
|
+
paymentIndex: 1,
|
|
1016
|
+
// Index of the payment transaction in the group
|
|
1017
|
+
paymentGroup: [
|
|
1018
|
+
unsignedFeeTxnBase64,
|
|
1019
|
+
// Transaction 0: unsigned fee tx
|
|
1020
|
+
signedPaymentTxnBase64
|
|
1021
|
+
// Transaction 1: signed payment tx
|
|
1022
|
+
]
|
|
931
1023
|
};
|
|
932
1024
|
return JSON.stringify(payload);
|
|
933
1025
|
} catch (error) {
|
|
@@ -946,6 +1038,29 @@ var AlgorandProvider = class {
|
|
|
946
1038
|
);
|
|
947
1039
|
}
|
|
948
1040
|
}
|
|
1041
|
+
/**
|
|
1042
|
+
* Decode signed transaction from wallet response (handles various formats)
|
|
1043
|
+
*/
|
|
1044
|
+
decodeSignedTxn(signedResult) {
|
|
1045
|
+
if (signedResult instanceof Uint8Array) {
|
|
1046
|
+
return signedResult;
|
|
1047
|
+
} else if (typeof signedResult === "string") {
|
|
1048
|
+
try {
|
|
1049
|
+
return Uint8Array.from(atob(signedResult), (c) => c.charCodeAt(0));
|
|
1050
|
+
} catch {
|
|
1051
|
+
const standardBase64 = signedResult.replace(/-/g, "+").replace(/_/g, "/");
|
|
1052
|
+
return Uint8Array.from(atob(standardBase64), (c) => c.charCodeAt(0));
|
|
1053
|
+
}
|
|
1054
|
+
} else if (ArrayBuffer.isView(signedResult)) {
|
|
1055
|
+
return new Uint8Array(
|
|
1056
|
+
signedResult.buffer,
|
|
1057
|
+
signedResult.byteOffset,
|
|
1058
|
+
signedResult.byteLength
|
|
1059
|
+
);
|
|
1060
|
+
} else {
|
|
1061
|
+
throw new X402Error("Unexpected signed transaction format", "PAYMENT_FAILED");
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
949
1064
|
/**
|
|
950
1065
|
* Encode Algorand payment as X-PAYMENT header
|
|
951
1066
|
*
|
|
@@ -956,14 +1071,15 @@ var AlgorandProvider = class {
|
|
|
956
1071
|
*/
|
|
957
1072
|
encodePaymentHeader(paymentPayload, chainConfig, version = 1) {
|
|
958
1073
|
const payload = JSON.parse(paymentPayload);
|
|
959
|
-
|
|
1074
|
+
let networkName;
|
|
1075
|
+
if (chainConfig?.name === "algorand-testnet") {
|
|
1076
|
+
networkName = "algorand-testnet";
|
|
1077
|
+
} else {
|
|
1078
|
+
networkName = "algorand-mainnet";
|
|
1079
|
+
}
|
|
960
1080
|
const payloadData = {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
amount: payload.amount,
|
|
964
|
-
assetId: payload.assetId,
|
|
965
|
-
signedTxn: payload.signedTxn,
|
|
966
|
-
...payload.note && { note: payload.note }
|
|
1081
|
+
paymentIndex: payload.paymentIndex,
|
|
1082
|
+
paymentGroup: payload.paymentGroup
|
|
967
1083
|
};
|
|
968
1084
|
const x402Payload = version === 2 ? {
|
|
969
1085
|
x402Version: 2,
|
|
@@ -975,7 +1091,6 @@ var AlgorandProvider = class {
|
|
|
975
1091
|
x402Version: 1,
|
|
976
1092
|
scheme: "exact",
|
|
977
1093
|
network: networkName,
|
|
978
|
-
// Plain chain name for v1
|
|
979
1094
|
payload: payloadData
|
|
980
1095
|
};
|
|
981
1096
|
return btoa(JSON.stringify(x402Payload));
|