uvd-x402-sdk 2.11.1 → 2.12.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 +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -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 +97 -27
- package/dist/providers/algorand/index.js.map +1 -1
- package/dist/providers/algorand/index.mjs +97 -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/providers/algorand/index.ts +117 -32
- package/src/types/index.ts +18 -22
|
@@ -877,11 +877,13 @@ var AlgorandProvider = class {
|
|
|
877
877
|
}
|
|
878
878
|
}
|
|
879
879
|
/**
|
|
880
|
-
* Create Algorand
|
|
880
|
+
* Create Algorand atomic group payment (GoPlausible x402-avm spec)
|
|
881
881
|
*
|
|
882
|
-
* Transaction structure:
|
|
883
|
-
*
|
|
884
|
-
*
|
|
882
|
+
* Transaction structure (atomic group):
|
|
883
|
+
* - Transaction 0: Fee payment (UNSIGNED) - facilitator -> facilitator, covers all fees
|
|
884
|
+
* - Transaction 1: ASA transfer (SIGNED) - client -> merchant
|
|
885
|
+
*
|
|
886
|
+
* The facilitator signs transaction 0 and submits the complete atomic group.
|
|
885
887
|
*/
|
|
886
888
|
async signPayment(paymentInfo, chainConfig) {
|
|
887
889
|
await loadAlgorandDeps();
|
|
@@ -894,40 +896,85 @@ var AlgorandProvider = class {
|
|
|
894
896
|
const algodClient = await this.getAlgodClient(chainConfig);
|
|
895
897
|
const recipient = paymentInfo.recipients?.algorand || paymentInfo.recipient;
|
|
896
898
|
const assetId = parseInt(chainConfig.usdc.address, 10);
|
|
899
|
+
const facilitatorAddress = paymentInfo.facilitator;
|
|
900
|
+
if (!facilitatorAddress) {
|
|
901
|
+
throw new X402Error(
|
|
902
|
+
"Facilitator address required for Algorand payments. Set paymentInfo.facilitator",
|
|
903
|
+
"PAYMENT_FAILED"
|
|
904
|
+
);
|
|
905
|
+
}
|
|
897
906
|
const amount = Math.floor(parseFloat(paymentInfo.amount) * 1e6);
|
|
898
907
|
try {
|
|
899
908
|
const suggestedParams = await algodClient.getTransactionParams().do();
|
|
900
|
-
const
|
|
909
|
+
const feeTxn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
|
|
910
|
+
sender: facilitatorAddress,
|
|
911
|
+
receiver: facilitatorAddress,
|
|
912
|
+
// self-transfer
|
|
913
|
+
amount: 0,
|
|
914
|
+
suggestedParams: {
|
|
915
|
+
...suggestedParams,
|
|
916
|
+
fee: 2e3,
|
|
917
|
+
// Covers both transactions (1000 each)
|
|
918
|
+
flatFee: true
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
const paymentTxn = algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({
|
|
901
922
|
sender: this.address,
|
|
902
923
|
receiver: recipient,
|
|
903
924
|
amount: BigInt(amount),
|
|
904
925
|
assetIndex: assetId,
|
|
905
|
-
suggestedParams
|
|
926
|
+
suggestedParams: {
|
|
927
|
+
...suggestedParams,
|
|
928
|
+
fee: 0,
|
|
929
|
+
// Fee paid by transaction 0
|
|
930
|
+
flatFee: true
|
|
931
|
+
},
|
|
906
932
|
note: new TextEncoder().encode("x402 payment via uvd-x402-sdk")
|
|
907
933
|
});
|
|
908
|
-
|
|
934
|
+
const txnGroup = algosdk.assignGroupID([feeTxn, paymentTxn]);
|
|
935
|
+
const unsignedFeeTxnBytes = algosdk.encodeUnsignedTransaction(txnGroup[0]);
|
|
936
|
+
const unsignedFeeTxnBase64 = uint8ArrayToBase64(unsignedFeeTxnBytes);
|
|
937
|
+
let signedPaymentTxnBytes;
|
|
909
938
|
if (this.walletType === "lute" && this.luteWallet) {
|
|
910
|
-
const
|
|
911
|
-
const
|
|
912
|
-
|
|
939
|
+
const feeTxnBase64 = uint8ArrayToBase64(txnGroup[0].toByte());
|
|
940
|
+
const paymentTxnBase64 = uint8ArrayToBase64(txnGroup[1].toByte());
|
|
941
|
+
const signedTxns = await this.luteWallet.signTxns([
|
|
942
|
+
{ txn: feeTxnBase64, signers: [] },
|
|
943
|
+
// Don't sign - facilitator will
|
|
944
|
+
{ txn: paymentTxnBase64 }
|
|
945
|
+
// Sign this one
|
|
946
|
+
]);
|
|
947
|
+
if (!signedTxns || signedTxns.length < 2 || !signedTxns[1]) {
|
|
913
948
|
throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
|
|
914
949
|
}
|
|
915
|
-
|
|
950
|
+
const signedResult = signedTxns[1];
|
|
951
|
+
signedPaymentTxnBytes = this.decodeSignedTxn(signedResult);
|
|
916
952
|
} else if (this.walletType === "pera" && this.peraWallet) {
|
|
917
|
-
const signedTxns = await this.peraWallet.signTransaction([
|
|
918
|
-
|
|
953
|
+
const signedTxns = await this.peraWallet.signTransaction([
|
|
954
|
+
[
|
|
955
|
+
{ txn: txnGroup[0], signers: [] },
|
|
956
|
+
// Don't sign - facilitator will
|
|
957
|
+
{ txn: txnGroup[1] }
|
|
958
|
+
// Sign this one
|
|
959
|
+
]
|
|
960
|
+
]);
|
|
961
|
+
if (!signedTxns || signedTxns.length < 2 || !signedTxns[1]) {
|
|
919
962
|
throw new X402Error("No signed transaction returned", "SIGNATURE_REJECTED");
|
|
920
963
|
}
|
|
921
|
-
|
|
964
|
+
signedPaymentTxnBytes = signedTxns[1];
|
|
922
965
|
} else {
|
|
923
966
|
throw new X402Error("No wallet available for signing", "WALLET_NOT_CONNECTED");
|
|
924
967
|
}
|
|
968
|
+
const signedPaymentTxnBase64 = uint8ArrayToBase64(signedPaymentTxnBytes);
|
|
925
969
|
const payload = {
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
970
|
+
paymentIndex: 1,
|
|
971
|
+
// Index of the payment transaction in the group
|
|
972
|
+
paymentGroup: [
|
|
973
|
+
unsignedFeeTxnBase64,
|
|
974
|
+
// Transaction 0: unsigned fee tx
|
|
975
|
+
signedPaymentTxnBase64
|
|
976
|
+
// Transaction 1: signed payment tx
|
|
977
|
+
]
|
|
931
978
|
};
|
|
932
979
|
return JSON.stringify(payload);
|
|
933
980
|
} catch (error) {
|
|
@@ -946,6 +993,29 @@ var AlgorandProvider = class {
|
|
|
946
993
|
);
|
|
947
994
|
}
|
|
948
995
|
}
|
|
996
|
+
/**
|
|
997
|
+
* Decode signed transaction from wallet response (handles various formats)
|
|
998
|
+
*/
|
|
999
|
+
decodeSignedTxn(signedResult) {
|
|
1000
|
+
if (signedResult instanceof Uint8Array) {
|
|
1001
|
+
return signedResult;
|
|
1002
|
+
} else if (typeof signedResult === "string") {
|
|
1003
|
+
try {
|
|
1004
|
+
return Uint8Array.from(atob(signedResult), (c) => c.charCodeAt(0));
|
|
1005
|
+
} catch {
|
|
1006
|
+
const standardBase64 = signedResult.replace(/-/g, "+").replace(/_/g, "/");
|
|
1007
|
+
return Uint8Array.from(atob(standardBase64), (c) => c.charCodeAt(0));
|
|
1008
|
+
}
|
|
1009
|
+
} else if (ArrayBuffer.isView(signedResult)) {
|
|
1010
|
+
return new Uint8Array(
|
|
1011
|
+
signedResult.buffer,
|
|
1012
|
+
signedResult.byteOffset,
|
|
1013
|
+
signedResult.byteLength
|
|
1014
|
+
);
|
|
1015
|
+
} else {
|
|
1016
|
+
throw new X402Error("Unexpected signed transaction format", "PAYMENT_FAILED");
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
949
1019
|
/**
|
|
950
1020
|
* Encode Algorand payment as X-PAYMENT header
|
|
951
1021
|
*
|
|
@@ -956,14 +1026,15 @@ var AlgorandProvider = class {
|
|
|
956
1026
|
*/
|
|
957
1027
|
encodePaymentHeader(paymentPayload, chainConfig, version = 1) {
|
|
958
1028
|
const payload = JSON.parse(paymentPayload);
|
|
959
|
-
|
|
1029
|
+
let networkName;
|
|
1030
|
+
if (chainConfig?.name === "algorand-testnet") {
|
|
1031
|
+
networkName = "algorand-testnet";
|
|
1032
|
+
} else {
|
|
1033
|
+
networkName = "algorand-mainnet";
|
|
1034
|
+
}
|
|
960
1035
|
const payloadData = {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
amount: payload.amount,
|
|
964
|
-
assetId: payload.assetId,
|
|
965
|
-
signedTxn: payload.signedTxn,
|
|
966
|
-
...payload.note && { note: payload.note }
|
|
1036
|
+
paymentIndex: payload.paymentIndex,
|
|
1037
|
+
paymentGroup: payload.paymentGroup
|
|
967
1038
|
};
|
|
968
1039
|
const x402Payload = version === 2 ? {
|
|
969
1040
|
x402Version: 2,
|
|
@@ -975,7 +1046,6 @@ var AlgorandProvider = class {
|
|
|
975
1046
|
x402Version: 1,
|
|
976
1047
|
scheme: "exact",
|
|
977
1048
|
network: networkName,
|
|
978
|
-
// Plain chain name for v1
|
|
979
1049
|
payload: payloadData
|
|
980
1050
|
};
|
|
981
1051
|
return btoa(JSON.stringify(x402Payload));
|