@nibgate/sdk 0.2.8 → 0.2.10
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/nibgate.js +151 -31
- package/dist/nibgate.js.map +3 -3
- package/dist/nibgate.min.js +2 -2
- package/dist/nibgate.min.js.map +4 -4
- package/package.json +6 -2
- package/src/browser/evm-gateway.js +4 -4
- package/src/browser/gateway.js +4 -33
- package/src/browser/schemes/batch-scheme.js +161 -0
- package/src/core/resource.js +0 -1
- package/src/index.d.ts +5 -1
package/dist/nibgate.js
CHANGED
|
@@ -33,32 +33,156 @@ var Nibgate = (() => {
|
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
// src/browser/schemes/batch-scheme.js
|
|
37
|
+
function supportsBatching(requirements) {
|
|
38
|
+
const extra = requirements.extra;
|
|
39
|
+
if (!extra) return false;
|
|
40
|
+
return extra.name === CIRCLE_BATCHING_NAME && extra.version === CIRCLE_BATCHING_VERSION;
|
|
41
|
+
}
|
|
42
|
+
function getVerifyingContract(requirements) {
|
|
43
|
+
if (!supportsBatching(requirements)) return void 0;
|
|
44
|
+
return requirements.extra?.verifyingContract;
|
|
45
|
+
}
|
|
46
|
+
function createNonce() {
|
|
47
|
+
const bytes = new Uint8Array(32);
|
|
48
|
+
crypto.getRandomValues(bytes);
|
|
49
|
+
return "0x" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
50
|
+
}
|
|
51
|
+
function getAddress(value) {
|
|
52
|
+
return value && typeof value === "string" && value.startsWith("0x") ? value.toLowerCase() : value;
|
|
53
|
+
}
|
|
54
|
+
var CIRCLE_BATCHING_NAME, CIRCLE_BATCHING_VERSION, GATEWAY_MIN_AUTH_VALIDITY_SECONDS, GATEWAY_AUTH_VALIDITY_WINDOW_SECONDS, authorizationTypes, BatchEvmScheme;
|
|
55
|
+
var init_batch_scheme = __esm({
|
|
56
|
+
"src/browser/schemes/batch-scheme.js"() {
|
|
57
|
+
CIRCLE_BATCHING_NAME = "GatewayWalletBatched";
|
|
58
|
+
CIRCLE_BATCHING_VERSION = "1";
|
|
59
|
+
GATEWAY_MIN_AUTH_VALIDITY_SECONDS = 7 * 24 * 60 * 60;
|
|
60
|
+
GATEWAY_AUTH_VALIDITY_WINDOW_SECONDS = GATEWAY_MIN_AUTH_VALIDITY_SECONDS + 100;
|
|
61
|
+
authorizationTypes = {
|
|
62
|
+
TransferWithAuthorization: [
|
|
63
|
+
{ name: "from", type: "address" },
|
|
64
|
+
{ name: "to", type: "address" },
|
|
65
|
+
{ name: "value", type: "uint256" },
|
|
66
|
+
{ name: "validAfter", type: "uint256" },
|
|
67
|
+
{ name: "validBefore", type: "uint256" },
|
|
68
|
+
{ name: "nonce", type: "bytes32" }
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
BatchEvmScheme = class {
|
|
72
|
+
constructor(signer) {
|
|
73
|
+
this.signer = signer;
|
|
74
|
+
this.scheme = CIRCLE_BATCHING_NAME;
|
|
75
|
+
this._beforeHooks = [];
|
|
76
|
+
this._afterHooks = [];
|
|
77
|
+
this._failureHooks = [];
|
|
78
|
+
}
|
|
79
|
+
onBeforePaymentCreation(hook) {
|
|
80
|
+
this._beforeHooks.push(hook);
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
onAfterPaymentCreation(hook) {
|
|
84
|
+
this._afterHooks.push(hook);
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
onPaymentCreationFailure(hook) {
|
|
88
|
+
this._failureHooks.push(hook);
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
async createPaymentPayload(x402Version, paymentRequirements) {
|
|
92
|
+
const context = {
|
|
93
|
+
paymentRequired: { x402Version, accepts: [paymentRequirements] },
|
|
94
|
+
selectedRequirements: paymentRequirements
|
|
95
|
+
};
|
|
96
|
+
for (const hook of this._beforeHooks) {
|
|
97
|
+
const result = await hook(context);
|
|
98
|
+
if (result && result.abort) {
|
|
99
|
+
throw new Error("Payment creation aborted: " + result.reason);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
if (!supportsBatching(paymentRequirements)) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
'BatchEvmScheme can only handle Circle batching options. Expected extra.name="' + CIRCLE_BATCHING_NAME + '" and extra.version="' + CIRCLE_BATCHING_VERSION + '"'
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
const verifyingContract = getVerifyingContract(paymentRequirements);
|
|
109
|
+
if (!verifyingContract) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
"Circle batching option missing extra.verifyingContract (GatewayWallet address)"
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const nonce = createNonce();
|
|
115
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
116
|
+
const validityWindowSeconds = Math.max(
|
|
117
|
+
paymentRequirements.maxTimeoutSeconds || 0,
|
|
118
|
+
GATEWAY_AUTH_VALIDITY_WINDOW_SECONDS
|
|
119
|
+
);
|
|
120
|
+
const authorization = {
|
|
121
|
+
from: getAddress(this.signer.address),
|
|
122
|
+
to: getAddress(paymentRequirements.payTo),
|
|
123
|
+
value: paymentRequirements.amount,
|
|
124
|
+
validAfter: String(now - 600),
|
|
125
|
+
validBefore: String(now + validityWindowSeconds),
|
|
126
|
+
nonce
|
|
127
|
+
};
|
|
128
|
+
const signature = await this.signAuthorization(authorization, paymentRequirements, verifyingContract);
|
|
129
|
+
const payload = { authorization, signature };
|
|
130
|
+
const result = { x402Version, payload };
|
|
131
|
+
const createdContext = { ...context, paymentPayload: result };
|
|
132
|
+
for (const hook of this._afterHooks) {
|
|
133
|
+
try {
|
|
134
|
+
await hook(createdContext);
|
|
135
|
+
} catch {
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
} catch (error) {
|
|
140
|
+
const failureContext = { ...context, error };
|
|
141
|
+
for (const hook of this._failureHooks) {
|
|
142
|
+
const result = await hook(failureContext);
|
|
143
|
+
if (result && result.recovered) {
|
|
144
|
+
return { x402Version: result.payload.x402Version, payload: result.payload.payload };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async signAuthorization(authorization, requirements, verifyingContract) {
|
|
151
|
+
if (!requirements.network.startsWith("eip155:")) {
|
|
152
|
+
throw new Error('BatchEvmScheme: unsupported network format "' + requirements.network + '". Expected "eip155:<chainId>"');
|
|
153
|
+
}
|
|
154
|
+
const chainId = parseInt(requirements.network.split(":")[1], 10);
|
|
155
|
+
const domain = {
|
|
156
|
+
name: CIRCLE_BATCHING_NAME,
|
|
157
|
+
version: CIRCLE_BATCHING_VERSION,
|
|
158
|
+
chainId,
|
|
159
|
+
verifyingContract: getAddress(verifyingContract)
|
|
160
|
+
};
|
|
161
|
+
const message = {
|
|
162
|
+
from: getAddress(authorization.from),
|
|
163
|
+
to: getAddress(authorization.to),
|
|
164
|
+
value: BigInt(authorization.value),
|
|
165
|
+
validAfter: BigInt(authorization.validAfter),
|
|
166
|
+
validBefore: BigInt(authorization.validBefore),
|
|
167
|
+
nonce: authorization.nonce
|
|
168
|
+
};
|
|
169
|
+
const typedData = {
|
|
170
|
+
domain,
|
|
171
|
+
types: authorizationTypes,
|
|
172
|
+
primaryType: "TransferWithAuthorization",
|
|
173
|
+
message
|
|
174
|
+
};
|
|
175
|
+
return this.signer.signTypedData(typedData);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
36
181
|
// src/browser/gateway.js
|
|
37
182
|
var gateway_exports = {};
|
|
38
183
|
__export(gateway_exports, {
|
|
39
184
|
createCircleGatewayBrowserAdapter: () => createCircleGatewayBrowserAdapter
|
|
40
185
|
});
|
|
41
|
-
async function getCircleClient(options = {}) {
|
|
42
|
-
if (cachedCircleModule) return cachedCircleModule;
|
|
43
|
-
if (options.clientModule) {
|
|
44
|
-
cachedCircleModule = options.clientModule;
|
|
45
|
-
return cachedCircleModule;
|
|
46
|
-
}
|
|
47
|
-
const moduleUrl = options.clientModuleUrl || "@circle-fin/x402-batching/client";
|
|
48
|
-
try {
|
|
49
|
-
cachedCircleModule = await import(moduleUrl);
|
|
50
|
-
return cachedCircleModule;
|
|
51
|
-
} catch (error) {
|
|
52
|
-
if (!options.clientModuleUrl) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
`Could not load @circle-fin/x402-batching/client from node_modules. Provide a clientModuleUrl option (e.g. "https://esm.sh/@circle-fin/x402-batching@3.2.0/client?bundle") to load from CDN. Original error: ${error.message}`
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
throw new Error(
|
|
58
|
-
`Could not load Circle Gateway client from CDN: ${error.message}. Check that ${options.clientModuleUrl} is reachable.`
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
186
|
function encodeBase64(value) {
|
|
63
187
|
const text = typeof value === "string" ? value : stringifyJson(value);
|
|
64
188
|
if (typeof Buffer !== "undefined") return Buffer.from(text).toString("base64");
|
|
@@ -73,9 +197,7 @@ var Nibgate = (() => {
|
|
|
73
197
|
if (!signer?.address || typeof signer.signTypedData !== "function") {
|
|
74
198
|
throw new Error("Circle Gateway browser adapter requires an EVM signer with address and signTypedData.");
|
|
75
199
|
}
|
|
76
|
-
const
|
|
77
|
-
const { BatchEvmScheme } = circleClientModule;
|
|
78
|
-
const scheme = new BatchEvmScheme(signer);
|
|
200
|
+
const scheme = options.clientModule?.BatchEvmScheme ? new options.clientModule.BatchEvmScheme(signer) : new BatchEvmScheme(signer);
|
|
79
201
|
const network = options.network || options.chainId && `eip155:${options.chainId}` || "eip155:5042002";
|
|
80
202
|
function parsePaymentRequired(input) {
|
|
81
203
|
if (input && typeof input === "object") return input;
|
|
@@ -131,11 +253,10 @@ var Nibgate = (() => {
|
|
|
131
253
|
}
|
|
132
254
|
};
|
|
133
255
|
}
|
|
134
|
-
var cachedCircleModule;
|
|
135
256
|
var init_gateway = __esm({
|
|
136
257
|
"src/browser/gateway.js"() {
|
|
258
|
+
init_batch_scheme();
|
|
137
259
|
init_json();
|
|
138
|
-
cachedCircleModule = null;
|
|
139
260
|
}
|
|
140
261
|
});
|
|
141
262
|
|
|
@@ -353,7 +474,6 @@ var Nibgate = (() => {
|
|
|
353
474
|
}
|
|
354
475
|
if (isPaidResource(normalized)) {
|
|
355
476
|
if (!hasValue(normalized.price)) errors.push("Paid content requires price.");
|
|
356
|
-
if (!hasValue(normalized.recipient || normalized.payTo)) warnings.push("Paid content should include recipient/payTo (server value from 402 challenge is used for actual payment).");
|
|
357
477
|
}
|
|
358
478
|
const score = Math.max(0, 100 - errors.length * 20 - warnings.length * 8);
|
|
359
479
|
return {
|
|
@@ -804,7 +924,6 @@ var Nibgate = (() => {
|
|
|
804
924
|
const gateway = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
|
|
805
925
|
return gateway.createCircleGatewayBrowserAdapter(options);
|
|
806
926
|
}
|
|
807
|
-
var DEFAULT_CIRCLE_CDN = "https://esm.sh/@circle-fin/x402-batching@3.2.0/client?bundle";
|
|
808
927
|
var HOSTED_PAY_URL = "https://api.nibgate.xyz/api/hub/pay";
|
|
809
928
|
function resolveAccessPath(resource, options) {
|
|
810
929
|
if (options.hosted || options.accessPath === "hosted") return HOSTED_PAY_URL;
|
|
@@ -903,8 +1022,7 @@ var Nibgate = (() => {
|
|
|
903
1022
|
address: walletAddress,
|
|
904
1023
|
signTypedData: (typedData) => evm.request({ method: "eth_signTypedData_v4", params: [walletAddress, stringifyJson(typedData)] })
|
|
905
1024
|
},
|
|
906
|
-
clientModule: options.circleClientModule
|
|
907
|
-
clientModuleUrl: options.circleClientModuleUrl || DEFAULT_CIRCLE_CDN
|
|
1025
|
+
clientModule: options.circleClientModule
|
|
908
1026
|
});
|
|
909
1027
|
return gatewayWallet.pay(input);
|
|
910
1028
|
}
|
|
@@ -921,6 +1039,9 @@ var Nibgate = (() => {
|
|
|
921
1039
|
challengeMessage: options.challengeMessage || "Gateway payment required. Connect your wallet to continue...",
|
|
922
1040
|
paymentMessage: options.paymentMessage || "Approve the Gateway payment proof in your wallet...",
|
|
923
1041
|
successMessage: options.successMessage || `Unlocked ${item.resource.title || "content"}.`,
|
|
1042
|
+
method: options.method,
|
|
1043
|
+
headers: options.headers,
|
|
1044
|
+
body: options.body,
|
|
924
1045
|
checkout,
|
|
925
1046
|
onStatus: setStatus
|
|
926
1047
|
});
|
|
@@ -970,7 +1091,6 @@ var Nibgate = (() => {
|
|
|
970
1091
|
return createEvmGatewayUnlock(resource, {
|
|
971
1092
|
...options,
|
|
972
1093
|
hosted: true,
|
|
973
|
-
circleClientModuleUrl: options.circleClientModuleUrl || DEFAULT_CIRCLE_CDN,
|
|
974
1094
|
noWalletMessage: options.noWalletMessage || "Install MetaMask or another EVM wallet to unlock premium content."
|
|
975
1095
|
});
|
|
976
1096
|
}
|