@kwespay/widget 1.0.6 → 1.0.8
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 +156 -0
- package/dist/esm/index.js +338 -359
- package/dist/kwespay-widget.js +339 -360
- package/dist/kwespay-widget.min.js +551 -551
- package/package.json +1 -1
package/dist/kwespay-widget.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
const STABLECOIN_SYMBOLS = ["USDT", "USDC", "DAI", "BUSD", "USDc"];
|
|
15
15
|
|
|
16
16
|
const DEFAULT_CONFIG = {
|
|
17
|
-
graphqlEndpoint: "https://
|
|
17
|
+
graphqlEndpoint: "https://api.kwespay.xyz/",
|
|
18
18
|
currency: SUPPORTED_CURRENCIES.USD,
|
|
19
19
|
};
|
|
20
20
|
|
|
@@ -16952,6 +16952,84 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
16952
16952
|
}
|
|
16953
16953
|
};
|
|
16954
16954
|
|
|
16955
|
+
function isMobileDevice() {
|
|
16956
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
16957
|
+
navigator.userAgent
|
|
16958
|
+
);
|
|
16959
|
+
}
|
|
16960
|
+
|
|
16961
|
+
function dispatchWidgetEvent(eventName, detail = {}) {
|
|
16962
|
+
const event = new CustomEvent(`kwespay:${eventName}`, {
|
|
16963
|
+
detail,
|
|
16964
|
+
bubbles: true,
|
|
16965
|
+
cancelable: true,
|
|
16966
|
+
});
|
|
16967
|
+
window.dispatchEvent(event);
|
|
16968
|
+
}
|
|
16969
|
+
|
|
16970
|
+
function truncateHash(hash, startChars = 10, endChars = 8) {
|
|
16971
|
+
if (!hash) return "";
|
|
16972
|
+
return `${hash.slice(0, startChars)}...${hash.slice(-endChars)}`;
|
|
16973
|
+
}
|
|
16974
|
+
|
|
16975
|
+
function getErrorType(error) {
|
|
16976
|
+
const msg = error?.message ?? "";
|
|
16977
|
+
if (
|
|
16978
|
+
error?.code === 4001 ||
|
|
16979
|
+
error?.code === "ACTION_REJECTED" ||
|
|
16980
|
+
msg.includes("rejected") ||
|
|
16981
|
+
msg.includes("denied") ||
|
|
16982
|
+
msg.includes("cancelled")
|
|
16983
|
+
)
|
|
16984
|
+
return "USER_REJECTED";
|
|
16985
|
+
if (msg.toLowerCase().includes("insufficient")) return "INSUFFICIENT_BALANCE";
|
|
16986
|
+
if (
|
|
16987
|
+
msg.includes("User rejected") ||
|
|
16988
|
+
msg.includes("User closed modal") ||
|
|
16989
|
+
msg.includes("Connection request reset")
|
|
16990
|
+
)
|
|
16991
|
+
return "CONNECTION_REJECTED";
|
|
16992
|
+
if (msg.includes("timeout")) return "TIMEOUT";
|
|
16993
|
+
return "UNKNOWN";
|
|
16994
|
+
}
|
|
16995
|
+
|
|
16996
|
+
function getErrorMessage(error, context = {}) {
|
|
16997
|
+
const type = getErrorType(error);
|
|
16998
|
+
|
|
16999
|
+
console.error("[KwesPay] Payment error breakdown:", {
|
|
17000
|
+
errorType: type,
|
|
17001
|
+
message: error?.message,
|
|
17002
|
+
code: error?.code,
|
|
17003
|
+
data: error?.data,
|
|
17004
|
+
reason: error?.reason,
|
|
17005
|
+
stack: error?.stack,
|
|
17006
|
+
raw: error,
|
|
17007
|
+
context,
|
|
17008
|
+
});
|
|
17009
|
+
|
|
17010
|
+
if (error?.data) console.error("[KwesPay] Contract revert data:", error.data);
|
|
17011
|
+
if (error?.transaction)
|
|
17012
|
+
console.error("[KwesPay] Failed tx details:", error.transaction);
|
|
17013
|
+
if (error?.receipt) console.error("[KwesPay] Tx receipt:", error.receipt);
|
|
17014
|
+
|
|
17015
|
+
switch (type) {
|
|
17016
|
+
case "USER_REJECTED":
|
|
17017
|
+
return "You cancelled the transaction in your wallet.";
|
|
17018
|
+
case "INSUFFICIENT_BALANCE":
|
|
17019
|
+
return `Not enough ${context.token || "funds"} to complete this payment.`;
|
|
17020
|
+
case "CONNECTION_REJECTED":
|
|
17021
|
+
return "Wallet connection was cancelled.";
|
|
17022
|
+
case "TIMEOUT":
|
|
17023
|
+
return "Connection timed out. Please try again.";
|
|
17024
|
+
default:
|
|
17025
|
+
return (
|
|
17026
|
+
error?.reason ||
|
|
17027
|
+
error?.message ||
|
|
17028
|
+
"Something went wrong while processing your payment."
|
|
17029
|
+
);
|
|
17030
|
+
}
|
|
17031
|
+
}
|
|
17032
|
+
|
|
16955
17033
|
const WIDGET_STYLES = `
|
|
16956
17034
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
|
16957
17035
|
|
|
@@ -18141,180 +18219,12 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18141
18219
|
`;
|
|
18142
18220
|
}
|
|
18143
18221
|
|
|
18144
|
-
|
|
18145
|
-
const event = new CustomEvent(`kwespay:${eventName}`, {
|
|
18146
|
-
detail,
|
|
18147
|
-
bubbles: true,
|
|
18148
|
-
cancelable: true,
|
|
18149
|
-
});
|
|
18150
|
-
window.dispatchEvent(event);
|
|
18151
|
-
}
|
|
18152
|
-
|
|
18153
|
-
function truncateHash(hash, startChars = 10, endChars = 8) {
|
|
18154
|
-
if (!hash) return "";
|
|
18155
|
-
return `${hash.slice(0, startChars)}...${hash.slice(-endChars)}`;
|
|
18156
|
-
}
|
|
18157
|
-
|
|
18158
|
-
function getErrorType(error) {
|
|
18159
|
-
const msg = error?.message ?? "";
|
|
18160
|
-
if (
|
|
18161
|
-
error?.code === 4001 ||
|
|
18162
|
-
error?.code === "ACTION_REJECTED" ||
|
|
18163
|
-
msg.includes("rejected") ||
|
|
18164
|
-
msg.includes("denied") ||
|
|
18165
|
-
msg.includes("cancelled")
|
|
18166
|
-
)
|
|
18167
|
-
return "USER_REJECTED";
|
|
18168
|
-
if (msg.toLowerCase().includes("insufficient")) return "INSUFFICIENT_BALANCE";
|
|
18169
|
-
if (
|
|
18170
|
-
msg.includes("User rejected") ||
|
|
18171
|
-
msg.includes("User closed modal") ||
|
|
18172
|
-
msg.includes("Connection request reset")
|
|
18173
|
-
)
|
|
18174
|
-
return "CONNECTION_REJECTED";
|
|
18175
|
-
if (msg.includes("timeout")) return "TIMEOUT";
|
|
18176
|
-
return "UNKNOWN";
|
|
18177
|
-
}
|
|
18178
|
-
|
|
18179
|
-
function getErrorMessage(error, context = {}) {
|
|
18180
|
-
const type = getErrorType(error);
|
|
18181
|
-
|
|
18182
|
-
console.error("[KwesPay] Payment error breakdown:", {
|
|
18183
|
-
errorType: type,
|
|
18184
|
-
message: error?.message,
|
|
18185
|
-
code: error?.code,
|
|
18186
|
-
data: error?.data,
|
|
18187
|
-
reason: error?.reason,
|
|
18188
|
-
stack: error?.stack,
|
|
18189
|
-
raw: error,
|
|
18190
|
-
context,
|
|
18191
|
-
});
|
|
18192
|
-
|
|
18193
|
-
if (error?.data) console.error("[KwesPay] Contract revert data:", error.data);
|
|
18194
|
-
if (error?.transaction)
|
|
18195
|
-
console.error("[KwesPay] Failed tx details:", error.transaction);
|
|
18196
|
-
if (error?.receipt) console.error("[KwesPay] Tx receipt:", error.receipt);
|
|
18197
|
-
|
|
18198
|
-
switch (type) {
|
|
18199
|
-
case "USER_REJECTED":
|
|
18200
|
-
return "You cancelled the transaction in your wallet.";
|
|
18201
|
-
case "INSUFFICIENT_BALANCE":
|
|
18202
|
-
return `Not enough ${context.token || "funds"} to complete this payment.`;
|
|
18203
|
-
case "CONNECTION_REJECTED":
|
|
18204
|
-
return "Wallet connection was cancelled.";
|
|
18205
|
-
case "TIMEOUT":
|
|
18206
|
-
return "Connection timed out. Please try again.";
|
|
18207
|
-
default:
|
|
18208
|
-
return (
|
|
18209
|
-
error?.reason ||
|
|
18210
|
-
error?.message ||
|
|
18211
|
-
"Something went wrong while processing your payment."
|
|
18212
|
-
);
|
|
18213
|
-
}
|
|
18214
|
-
}
|
|
18215
|
-
|
|
18216
|
-
const PLATFORM_FEE_BPS = 25;
|
|
18217
|
-
|
|
18218
|
-
// ── Utilities ─────────────────────────────────────────────────────────────────
|
|
18219
|
-
|
|
18220
|
-
function formatUnits$1(rawBigInt, decimals) {
|
|
18221
|
-
const divisor = BigInt(10 ** decimals);
|
|
18222
|
-
const whole = rawBigInt / divisor;
|
|
18223
|
-
const remainder = rawBigInt % divisor;
|
|
18224
|
-
|
|
18225
|
-
if (remainder === 0n) return `${whole}`;
|
|
18226
|
-
|
|
18227
|
-
const fracFull = remainder.toString().padStart(decimals, "0");
|
|
18228
|
-
|
|
18229
|
-
if (whole > 0n) {
|
|
18230
|
-
const frac = fracFull.slice(0, 4).replace(/0+$/, "");
|
|
18231
|
-
return frac ? `${whole}.${frac}` : `${whole}`;
|
|
18232
|
-
}
|
|
18233
|
-
|
|
18234
|
-
let firstSig = -1;
|
|
18235
|
-
for (let i = 0; i < fracFull.length; i++) {
|
|
18236
|
-
if (fracFull[i] !== "0") {
|
|
18237
|
-
firstSig = i;
|
|
18238
|
-
break;
|
|
18239
|
-
}
|
|
18240
|
-
}
|
|
18241
|
-
if (firstSig === -1) return `${whole}`;
|
|
18242
|
-
|
|
18243
|
-
const sigSlice = fracFull.slice(firstSig, firstSig + 4).replace(/0+$/, "");
|
|
18244
|
-
return `0.${fracFull.slice(0, firstSig) + sigSlice}`;
|
|
18245
|
-
}
|
|
18246
|
-
|
|
18247
|
-
function resolveAcceptedTokens(input) {
|
|
18248
|
-
if (!input) return null;
|
|
18249
|
-
if (input === "stablecoins") return STABLECOIN_SYMBOLS;
|
|
18250
|
-
if (Array.isArray(input) && input.length)
|
|
18251
|
-
return input.map((t) => t.toUpperCase());
|
|
18252
|
-
return null;
|
|
18253
|
-
}
|
|
18254
|
-
|
|
18255
|
-
function isMobileDevice() {
|
|
18256
|
-
return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
|
|
18257
|
-
}
|
|
18258
|
-
|
|
18259
|
-
// ── Widget ────────────────────────────────────────────────────────────────────
|
|
18260
|
-
|
|
18261
|
-
class KwesPayWidget {
|
|
18262
|
-
constructor(config) {
|
|
18263
|
-
if (!config.apiKey) throw new Error("[KwesPayWidget] apiKey is required");
|
|
18264
|
-
if (!config.vendorId)
|
|
18265
|
-
throw new Error("[KwesPayWidget] vendorId is required");
|
|
18266
|
-
if (!config.amount || parseFloat(config.amount) <= 0)
|
|
18267
|
-
throw new Error("[KwesPayWidget] Valid amount is required");
|
|
18268
|
-
|
|
18269
|
-
this.config = {
|
|
18270
|
-
apiKey: config.apiKey,
|
|
18271
|
-
vendorId: config.vendorId,
|
|
18272
|
-
amount: parseFloat(config.amount),
|
|
18273
|
-
currency: config.currency || DEFAULT_CONFIG.currency,
|
|
18274
|
-
graphqlEndpoint: DEFAULT_CONFIG.graphqlEndpoint,
|
|
18275
|
-
acceptedTokens: resolveAcceptedTokens(config.acceptedTokens),
|
|
18276
|
-
};
|
|
18277
|
-
|
|
18278
|
-
if (!Object.values(SUPPORTED_CURRENCIES).includes(this.config.currency)) {
|
|
18279
|
-
throw new Error(
|
|
18280
|
-
`[KwesPayWidget] Unsupported currency: ${this.config.currency}`
|
|
18281
|
-
);
|
|
18282
|
-
}
|
|
18283
|
-
|
|
18284
|
-
this.walletService = new WalletService();
|
|
18285
|
-
this.paymentService = new PaymentService$1(
|
|
18286
|
-
this.config.apiKey,
|
|
18287
|
-
this.config.graphqlEndpoint
|
|
18288
|
-
);
|
|
18289
|
-
|
|
18290
|
-
this.state = {
|
|
18291
|
-
isOpen: false,
|
|
18292
|
-
currentStep: 0,
|
|
18293
|
-
selectedNetwork: null,
|
|
18294
|
-
selectedNetworkName: "",
|
|
18295
|
-
selectedChainId: null,
|
|
18296
|
-
selectedRpcUrl: null,
|
|
18297
|
-
selectedContractAddress: null,
|
|
18298
|
-
selectedToken: null,
|
|
18299
|
-
selectedTokenConfig: null,
|
|
18300
|
-
vendorInfo: null,
|
|
18301
|
-
keyAllowedNetworks: null,
|
|
18302
|
-
keyAllowedTokens: null,
|
|
18303
|
-
currentPayload: null,
|
|
18304
|
-
quoteTimerInterval: null,
|
|
18305
|
-
wcUri: null,
|
|
18306
|
-
};
|
|
18307
|
-
|
|
18308
|
-
this._init();
|
|
18309
|
-
}
|
|
18310
|
-
|
|
18311
|
-
// ── Bootstrap ───────────────────────────────────────────────────────────────
|
|
18312
|
-
|
|
18222
|
+
const DomMethods = {
|
|
18313
18223
|
_init() {
|
|
18314
18224
|
this._injectFonts();
|
|
18315
18225
|
this._injectStyles();
|
|
18316
18226
|
this._createWidgetDOM();
|
|
18317
|
-
}
|
|
18227
|
+
},
|
|
18318
18228
|
|
|
18319
18229
|
_injectFonts() {
|
|
18320
18230
|
if (
|
|
@@ -18328,7 +18238,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18328
18238
|
link.rel = "stylesheet";
|
|
18329
18239
|
document.head.appendChild(link);
|
|
18330
18240
|
}
|
|
18331
|
-
}
|
|
18241
|
+
},
|
|
18332
18242
|
|
|
18333
18243
|
_injectStyles() {
|
|
18334
18244
|
if (!document.getElementById("kwespay-widget-styles")) {
|
|
@@ -18337,7 +18247,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18337
18247
|
style.textContent = WIDGET_STYLES;
|
|
18338
18248
|
document.head.appendChild(style);
|
|
18339
18249
|
}
|
|
18340
|
-
}
|
|
18250
|
+
},
|
|
18341
18251
|
|
|
18342
18252
|
_createWidgetDOM() {
|
|
18343
18253
|
document.getElementById("kwespay-widget-overlay")?.remove();
|
|
@@ -18364,15 +18274,16 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18364
18274
|
document.body.appendChild(overlay);
|
|
18365
18275
|
|
|
18366
18276
|
this._setupEventListeners();
|
|
18277
|
+
this._setupSwipeToClose(container);
|
|
18367
18278
|
|
|
18368
|
-
|
|
18369
|
-
|
|
18370
|
-
});
|
|
18279
|
+
// Clicking outside the container does NOT close the widget (intentional)
|
|
18280
|
+
},
|
|
18371
18281
|
|
|
18372
|
-
|
|
18282
|
+
_setupSwipeToClose(container) {
|
|
18373
18283
|
let _touchStartY = 0,
|
|
18374
18284
|
_touchCurrentY = 0,
|
|
18375
18285
|
_isDragging = false;
|
|
18286
|
+
|
|
18376
18287
|
container.addEventListener(
|
|
18377
18288
|
"touchstart",
|
|
18378
18289
|
(e) => {
|
|
@@ -18387,6 +18298,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18387
18298
|
},
|
|
18388
18299
|
{ passive: true }
|
|
18389
18300
|
);
|
|
18301
|
+
|
|
18390
18302
|
container.addEventListener(
|
|
18391
18303
|
"touchmove",
|
|
18392
18304
|
(e) => {
|
|
@@ -18397,6 +18309,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18397
18309
|
},
|
|
18398
18310
|
{ passive: true }
|
|
18399
18311
|
);
|
|
18312
|
+
|
|
18400
18313
|
container.addEventListener("touchend", () => {
|
|
18401
18314
|
if (!_isDragging) return;
|
|
18402
18315
|
_isDragging = false;
|
|
@@ -18405,7 +18318,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18405
18318
|
if (delta > 120) this.close();
|
|
18406
18319
|
else container.style.transform = "translateY(0)";
|
|
18407
18320
|
});
|
|
18408
|
-
}
|
|
18321
|
+
},
|
|
18409
18322
|
|
|
18410
18323
|
_setupEventListeners() {
|
|
18411
18324
|
document
|
|
@@ -18514,10 +18427,83 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18514
18427
|
});
|
|
18515
18428
|
});
|
|
18516
18429
|
}
|
|
18517
|
-
}
|
|
18518
|
-
|
|
18519
|
-
|
|
18430
|
+
},
|
|
18431
|
+
};
|
|
18432
|
+
|
|
18433
|
+
const NavMethods = {
|
|
18434
|
+
_goToStep(stepNumber) {
|
|
18435
|
+
document
|
|
18436
|
+
.querySelectorAll(".kwespay-container .step")
|
|
18437
|
+
.forEach((s) => s.classList.remove("active", "exiting"));
|
|
18438
|
+
this._activateStep(stepNumber);
|
|
18439
|
+
this.state.currentStep = stepNumber;
|
|
18440
|
+
},
|
|
18441
|
+
|
|
18442
|
+
_activateStep(stepNumber) {
|
|
18443
|
+
let targetStep;
|
|
18444
|
+
if (stepNumber === 0.5)
|
|
18445
|
+
targetStep = document.getElementById("kwespay-step0-invalid");
|
|
18446
|
+
else if (typeof stepNumber === "string")
|
|
18447
|
+
targetStep = document.getElementById(`kwespay-step-${stepNumber}`);
|
|
18448
|
+
else targetStep = document.getElementById(`kwespay-step${stepNumber}`);
|
|
18449
|
+
|
|
18450
|
+
if (targetStep) targetStep.classList.add("active");
|
|
18451
|
+
else console.warn(`[KwesPayWidget] Step not found: ${stepNumber}`);
|
|
18452
|
+
},
|
|
18453
|
+
|
|
18454
|
+
_removeCustomStep(id) {
|
|
18455
|
+
document.getElementById(id)?.remove();
|
|
18456
|
+
},
|
|
18457
|
+
|
|
18458
|
+
_showError(title, message) {
|
|
18459
|
+
const titleEl = document.getElementById("kwespay-errorTitle");
|
|
18460
|
+
const msgEl = document.getElementById("kwespay-errorMessage");
|
|
18461
|
+
if (titleEl) titleEl.textContent = title;
|
|
18462
|
+
if (msgEl) msgEl.textContent = message;
|
|
18463
|
+
this._goToStep(6);
|
|
18464
|
+
},
|
|
18465
|
+
|
|
18466
|
+
_reset() {
|
|
18467
|
+
this._clearQuoteTimer();
|
|
18468
|
+
this._removeCustomStep("kwespay-step-wallet-picker");
|
|
18469
|
+
this._removeCustomStep("kwespay-step-wc");
|
|
18470
|
+
this.state.selectedNetwork = null;
|
|
18471
|
+
this.state.selectedNetworkName = "";
|
|
18472
|
+
this.state.selectedChainId = null;
|
|
18473
|
+
this.state.selectedRpcUrl = null;
|
|
18474
|
+
this.state.selectedContractAddress = null;
|
|
18475
|
+
this.state.selectedToken = null;
|
|
18476
|
+
this.state.selectedTokenConfig = null;
|
|
18477
|
+
this.state.currentPayload = null;
|
|
18478
|
+
this.state.wcUri = null;
|
|
18479
|
+
},
|
|
18480
|
+
};
|
|
18520
18481
|
|
|
18482
|
+
const APIKeyMethods = {
|
|
18483
|
+
async _validateAPIKey() {
|
|
18484
|
+
try {
|
|
18485
|
+
const validation = await this.paymentService.validateAPIKey();
|
|
18486
|
+
if (validation.valid) {
|
|
18487
|
+
this.state.vendorInfo = validation.vendorInfo;
|
|
18488
|
+
this.state.keyAllowedNetworks = validation.allowedNetworks ?? null;
|
|
18489
|
+
this.state.keyAllowedTokens = validation.allowedTokens ?? null;
|
|
18490
|
+
this._goToStep(1);
|
|
18491
|
+
dispatchWidgetEvent("apiKeyValidated", {
|
|
18492
|
+
vendorInfo: this.state.vendorInfo,
|
|
18493
|
+
});
|
|
18494
|
+
} else {
|
|
18495
|
+
this._goToStep(0.5);
|
|
18496
|
+
dispatchWidgetEvent("apiKeyInvalid", {});
|
|
18497
|
+
}
|
|
18498
|
+
} catch (err) {
|
|
18499
|
+
console.error("[KwesPayWidget] API key validation error:", err.message);
|
|
18500
|
+
this._goToStep(0.5);
|
|
18501
|
+
dispatchWidgetEvent("apiKeyError", { error: err.message });
|
|
18502
|
+
}
|
|
18503
|
+
},
|
|
18504
|
+
};
|
|
18505
|
+
|
|
18506
|
+
const NetworkMethods = {
|
|
18521
18507
|
_renderNetworkList() {
|
|
18522
18508
|
const mainnetList = document.getElementById("kwespay-mainnetList");
|
|
18523
18509
|
const testnetList = document.getElementById("kwespay-testnetList");
|
|
@@ -18579,7 +18565,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18579
18565
|
|
|
18580
18566
|
if (testnetSection)
|
|
18581
18567
|
testnetSection.style.display = hasTestnet ? "block" : "none";
|
|
18582
|
-
}
|
|
18568
|
+
},
|
|
18583
18569
|
|
|
18584
18570
|
_renderTokenList() {
|
|
18585
18571
|
if (!this.state.selectedNetwork) return;
|
|
@@ -18618,7 +18604,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18618
18604
|
);
|
|
18619
18605
|
tokenList.appendChild(tokenItem);
|
|
18620
18606
|
});
|
|
18621
|
-
}
|
|
18607
|
+
},
|
|
18622
18608
|
|
|
18623
18609
|
_effectiveAllowedTokens() {
|
|
18624
18610
|
const keyTokens =
|
|
@@ -18628,17 +18614,64 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18628
18614
|
if (!keyTokens) return configTokens;
|
|
18629
18615
|
if (!configTokens) return keyTokens;
|
|
18630
18616
|
return keyTokens.filter((t) => configTokens.includes(t));
|
|
18631
|
-
}
|
|
18617
|
+
},
|
|
18618
|
+
|
|
18619
|
+
async _handleNetworkSelection(key, network) {
|
|
18620
|
+
this.state.selectedNetwork = key;
|
|
18621
|
+
this.state.selectedNetworkName = network.name;
|
|
18622
|
+
this.state.selectedChainId = network.chainId;
|
|
18623
|
+
this.state.selectedRpcUrl = network.rpcUrl;
|
|
18624
|
+
this.state.selectedContractAddress = network.contractAddress;
|
|
18625
|
+
this.state.selectedToken = null;
|
|
18626
|
+
this.state.selectedTokenConfig = null;
|
|
18627
|
+
|
|
18628
|
+
const nameEl = document.getElementById("kwespay-selectedNetworkName");
|
|
18629
|
+
if (nameEl)
|
|
18630
|
+
nameEl.textContent = `${network.name} ${
|
|
18631
|
+
network.type === "mainnet" ? "Mainnet" : "Testnet"
|
|
18632
|
+
}`;
|
|
18633
|
+
|
|
18634
|
+
const iconEl = document.getElementById("kwespay-selectedNetworkIcon");
|
|
18635
|
+
if (iconEl)
|
|
18636
|
+
iconEl.innerHTML = `<img src="${network.logo}" alt="${network.name}" />`;
|
|
18632
18637
|
|
|
18633
|
-
|
|
18638
|
+
const continueBtn = document.getElementById(
|
|
18639
|
+
"kwespay-continueToWalletConnect"
|
|
18640
|
+
);
|
|
18641
|
+
if (continueBtn) continueBtn.disabled = true;
|
|
18634
18642
|
|
|
18643
|
+
this._renderTokenList();
|
|
18644
|
+
this._goToStep(2);
|
|
18645
|
+
},
|
|
18646
|
+
|
|
18647
|
+
_handleTokenSelection(token) {
|
|
18648
|
+
document
|
|
18649
|
+
.querySelectorAll("#kwespay-tokenList .token-item")
|
|
18650
|
+
.forEach((item) => item.classList.remove("selected"));
|
|
18651
|
+
document
|
|
18652
|
+
.querySelector(
|
|
18653
|
+
`#kwespay-tokenList .token-item[data-token-symbol="${token.symbol}"]`
|
|
18654
|
+
)
|
|
18655
|
+
?.classList.add("selected");
|
|
18656
|
+
|
|
18657
|
+
this.state.selectedToken = token.symbol;
|
|
18658
|
+
this.state.selectedTokenConfig = token;
|
|
18659
|
+
|
|
18660
|
+
const continueBtn = document.getElementById(
|
|
18661
|
+
"kwespay-continueToWalletConnect"
|
|
18662
|
+
);
|
|
18663
|
+
if (continueBtn) continueBtn.disabled = false;
|
|
18664
|
+
},
|
|
18665
|
+
};
|
|
18666
|
+
|
|
18667
|
+
const WalletMethods = {
|
|
18635
18668
|
async _handleWalletConnection() {
|
|
18636
18669
|
if (!this.state.selectedToken || !this.state.selectedTokenConfig) {
|
|
18637
18670
|
alert("Please select a token first");
|
|
18638
18671
|
return;
|
|
18639
18672
|
}
|
|
18640
18673
|
this._renderWalletPickerStep();
|
|
18641
|
-
}
|
|
18674
|
+
},
|
|
18642
18675
|
|
|
18643
18676
|
_renderWalletPickerStep() {
|
|
18644
18677
|
this._removeCustomStep("kwespay-step-wallet-picker");
|
|
@@ -18736,7 +18769,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18736
18769
|
list.appendChild(item);
|
|
18737
18770
|
});
|
|
18738
18771
|
});
|
|
18739
|
-
}
|
|
18772
|
+
},
|
|
18740
18773
|
|
|
18741
18774
|
async _connectInjectedProvider(index) {
|
|
18742
18775
|
try {
|
|
@@ -18751,7 +18784,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18751
18784
|
);
|
|
18752
18785
|
dispatchWidgetEvent("walletConnectionError", { error: err.message });
|
|
18753
18786
|
}
|
|
18754
|
-
}
|
|
18787
|
+
},
|
|
18755
18788
|
|
|
18756
18789
|
async _startWalletConnect() {
|
|
18757
18790
|
this._renderWCStep();
|
|
@@ -18767,7 +18800,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18767
18800
|
this._renderWCMobileStep();
|
|
18768
18801
|
}
|
|
18769
18802
|
|
|
18770
|
-
// Pass the target chain so
|
|
18803
|
+
// Pass the target chain so the wallet starts the WC session on the right
|
|
18771
18804
|
// network — without this it defaults to its last-used WC chain (Mainnet).
|
|
18772
18805
|
await this.walletService.connectWalletConnect(this.state.selectedChainId);
|
|
18773
18806
|
} catch (err) {
|
|
@@ -18782,9 +18815,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18782
18815
|
err.message || "WalletConnect failed."
|
|
18783
18816
|
);
|
|
18784
18817
|
}
|
|
18785
|
-
}
|
|
18786
|
-
|
|
18787
|
-
// ── WalletConnect UI ─────────────────────────────────────────────────────────
|
|
18818
|
+
},
|
|
18788
18819
|
|
|
18789
18820
|
_renderWCStep() {
|
|
18790
18821
|
this._removeCustomStep("kwespay-step-wc");
|
|
@@ -18817,7 +18848,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18817
18848
|
});
|
|
18818
18849
|
|
|
18819
18850
|
this._goToStep("wc");
|
|
18820
|
-
}
|
|
18851
|
+
},
|
|
18821
18852
|
|
|
18822
18853
|
_wcDesktopHTML() {
|
|
18823
18854
|
return `
|
|
@@ -18839,7 +18870,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18839
18870
|
<p style="font-size:11px;color:var(--kp-muted);font-family:var(--kp-mono);text-align:center">Waiting for wallet connection…</p>
|
|
18840
18871
|
</div>
|
|
18841
18872
|
`;
|
|
18842
|
-
}
|
|
18873
|
+
},
|
|
18843
18874
|
|
|
18844
18875
|
_wcMobileHTML() {
|
|
18845
18876
|
const wallets = this.walletService.getMobileWallets();
|
|
@@ -18887,7 +18918,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18887
18918
|
</p>
|
|
18888
18919
|
</div>
|
|
18889
18920
|
`;
|
|
18890
|
-
}
|
|
18921
|
+
},
|
|
18891
18922
|
|
|
18892
18923
|
_renderWCMobileStep() {
|
|
18893
18924
|
const list = document.getElementById("kwespay-mobile-wallet-list");
|
|
@@ -18911,7 +18942,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18911
18942
|
}
|
|
18912
18943
|
});
|
|
18913
18944
|
});
|
|
18914
|
-
}
|
|
18945
|
+
},
|
|
18915
18946
|
|
|
18916
18947
|
_onWCUri(uri) {
|
|
18917
18948
|
this.state.wcUri = uri;
|
|
@@ -18928,7 +18959,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18928
18959
|
} else {
|
|
18929
18960
|
this._renderQRCode(uri);
|
|
18930
18961
|
}
|
|
18931
|
-
}
|
|
18962
|
+
},
|
|
18932
18963
|
|
|
18933
18964
|
_renderQRCode(uri) {
|
|
18934
18965
|
const canvas = document.getElementById("kwespay-qr-canvas");
|
|
@@ -18963,18 +18994,18 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18963
18994
|
<p style="font-size:10px;color:#888;font-family:monospace">Use Copy URI button</p>
|
|
18964
18995
|
</div>
|
|
18965
18996
|
`;
|
|
18966
|
-
}
|
|
18997
|
+
},
|
|
18967
18998
|
|
|
18968
18999
|
_onWCConnected() {
|
|
18969
19000
|
const connection = this.walletService._connectionResult();
|
|
18970
19001
|
this._removeCustomStep("kwespay-step-wc");
|
|
18971
19002
|
this._onWalletConnected(connection);
|
|
18972
|
-
}
|
|
19003
|
+
},
|
|
18973
19004
|
|
|
18974
19005
|
_onWCDisconnected() {
|
|
18975
19006
|
this._removeCustomStep("kwespay-step-wc");
|
|
18976
19007
|
this._goToStep(2);
|
|
18977
|
-
}
|
|
19008
|
+
},
|
|
18978
19009
|
|
|
18979
19010
|
async _onWalletConnected(connection) {
|
|
18980
19011
|
const addressEl = document.getElementById("kwespay-connectedWalletAddress");
|
|
@@ -18991,7 +19022,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
18991
19022
|
const proceedBtn = document.getElementById("kwespay-proceedToPayment");
|
|
18992
19023
|
|
|
18993
19024
|
if (cryptoLine) {
|
|
18994
|
-
cryptoLine.textContent = "
|
|
19025
|
+
cryptoLine.textContent = "loading…";
|
|
18995
19026
|
cryptoLine.classList.add("loading");
|
|
18996
19027
|
}
|
|
18997
19028
|
if (timerEl) timerEl.style.display = "none";
|
|
@@ -19013,83 +19044,39 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19013
19044
|
}
|
|
19014
19045
|
|
|
19015
19046
|
dispatchWidgetEvent("walletConnected", { address: connection.address });
|
|
19016
|
-
}
|
|
19017
|
-
|
|
19018
|
-
// ── API key validation ───────────────────────────────────────────────────────
|
|
19019
|
-
|
|
19020
|
-
async _validateAPIKey() {
|
|
19021
|
-
try {
|
|
19022
|
-
const validation = await this.paymentService.validateAPIKey();
|
|
19023
|
-
if (validation.valid) {
|
|
19024
|
-
this.state.vendorInfo = validation.vendorInfo;
|
|
19025
|
-
this.state.keyAllowedNetworks = validation.allowedNetworks ?? null;
|
|
19026
|
-
this.state.keyAllowedTokens = validation.allowedTokens ?? null;
|
|
19027
|
-
this._goToStep(1);
|
|
19028
|
-
dispatchWidgetEvent("apiKeyValidated", {
|
|
19029
|
-
vendorInfo: this.state.vendorInfo,
|
|
19030
|
-
});
|
|
19031
|
-
} else {
|
|
19032
|
-
this._goToStep(0.5);
|
|
19033
|
-
dispatchWidgetEvent("apiKeyInvalid", {});
|
|
19034
|
-
}
|
|
19035
|
-
} catch (err) {
|
|
19036
|
-
console.error("[KwesPayWidget] API key validation error:", err.message);
|
|
19037
|
-
this._goToStep(0.5);
|
|
19038
|
-
dispatchWidgetEvent("apiKeyError", { error: err.message });
|
|
19039
|
-
}
|
|
19040
|
-
}
|
|
19041
|
-
|
|
19042
|
-
// ── Network / token selection ────────────────────────────────────────────────
|
|
19047
|
+
},
|
|
19048
|
+
};
|
|
19043
19049
|
|
|
19044
|
-
|
|
19045
|
-
this.state.selectedNetwork = key;
|
|
19046
|
-
this.state.selectedNetworkName = network.name;
|
|
19047
|
-
this.state.selectedChainId = network.chainId;
|
|
19048
|
-
this.state.selectedRpcUrl = network.rpcUrl;
|
|
19049
|
-
this.state.selectedContractAddress = network.contractAddress;
|
|
19050
|
-
this.state.selectedToken = null;
|
|
19051
|
-
this.state.selectedTokenConfig = null;
|
|
19050
|
+
const PLATFORM_FEE_BPS = 25;
|
|
19052
19051
|
|
|
19053
|
-
|
|
19054
|
-
|
|
19055
|
-
|
|
19056
|
-
|
|
19057
|
-
}`;
|
|
19052
|
+
function formatUnits$1(rawBigInt, decimals) {
|
|
19053
|
+
const divisor = BigInt(10 ** decimals);
|
|
19054
|
+
const whole = rawBigInt / divisor;
|
|
19055
|
+
const remainder = rawBigInt % divisor;
|
|
19058
19056
|
|
|
19059
|
-
|
|
19060
|
-
if (iconEl)
|
|
19061
|
-
iconEl.innerHTML = `<img src="${network.logo}" alt="${network.name}" />`;
|
|
19057
|
+
if (remainder === 0n) return `${whole}`;
|
|
19062
19058
|
|
|
19063
|
-
|
|
19064
|
-
"kwespay-continueToWalletConnect"
|
|
19065
|
-
);
|
|
19066
|
-
if (continueBtn) continueBtn.disabled = true;
|
|
19059
|
+
const fracFull = remainder.toString().padStart(decimals, "0");
|
|
19067
19060
|
|
|
19068
|
-
|
|
19069
|
-
|
|
19061
|
+
if (whole > 0n) {
|
|
19062
|
+
const frac = fracFull.slice(0, 4).replace(/0+$/, "");
|
|
19063
|
+
return frac ? `${whole}.${frac}` : `${whole}`;
|
|
19070
19064
|
}
|
|
19071
19065
|
|
|
19072
|
-
|
|
19073
|
-
|
|
19074
|
-
|
|
19075
|
-
|
|
19076
|
-
|
|
19077
|
-
|
|
19078
|
-
`#kwespay-tokenList .token-item[data-token-symbol="${token.symbol}"]`
|
|
19079
|
-
)
|
|
19080
|
-
?.classList.add("selected");
|
|
19081
|
-
|
|
19082
|
-
this.state.selectedToken = token.symbol;
|
|
19083
|
-
this.state.selectedTokenConfig = token;
|
|
19084
|
-
|
|
19085
|
-
const continueBtn = document.getElementById(
|
|
19086
|
-
"kwespay-continueToWalletConnect"
|
|
19087
|
-
);
|
|
19088
|
-
if (continueBtn) continueBtn.disabled = false;
|
|
19066
|
+
let firstSig = -1;
|
|
19067
|
+
for (let i = 0; i < fracFull.length; i++) {
|
|
19068
|
+
if (fracFull[i] !== "0") {
|
|
19069
|
+
firstSig = i;
|
|
19070
|
+
break;
|
|
19071
|
+
}
|
|
19089
19072
|
}
|
|
19073
|
+
if (firstSig === -1) return `${whole}`;
|
|
19090
19074
|
|
|
19091
|
-
|
|
19075
|
+
const sigSlice = fracFull.slice(firstSig, firstSig + 4).replace(/0+$/, "");
|
|
19076
|
+
return `0.${fracFull.slice(0, firstSig) + sigSlice}`;
|
|
19077
|
+
}
|
|
19092
19078
|
|
|
19079
|
+
const QuoteMethods = {
|
|
19093
19080
|
async _loadReviewStep() {
|
|
19094
19081
|
this._clearQuoteTimer();
|
|
19095
19082
|
|
|
@@ -19101,7 +19088,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19101
19088
|
const proceedBtn = document.getElementById("kwespay-proceedToPayment");
|
|
19102
19089
|
|
|
19103
19090
|
if (cryptoLine) {
|
|
19104
|
-
cryptoLine.textContent = "
|
|
19091
|
+
cryptoLine.textContent = "loading…";
|
|
19105
19092
|
cryptoLine.classList.add("loading");
|
|
19106
19093
|
}
|
|
19107
19094
|
if (timerEl) timerEl.style.display = "none";
|
|
@@ -19141,12 +19128,12 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19141
19128
|
} catch (err) {
|
|
19142
19129
|
console.error("[KwesPayWidget] Quote fetch failed:", err.message);
|
|
19143
19130
|
if (cryptoLine) {
|
|
19144
|
-
cryptoLine.textContent = "Could not load
|
|
19131
|
+
cryptoLine.textContent = "Could not load please try again.";
|
|
19145
19132
|
cryptoLine.classList.remove("loading");
|
|
19146
19133
|
}
|
|
19147
19134
|
if (proceedBtn) proceedBtn.disabled = true;
|
|
19148
19135
|
}
|
|
19149
|
-
}
|
|
19136
|
+
},
|
|
19150
19137
|
|
|
19151
19138
|
_startQuoteTimer(expiresAt) {
|
|
19152
19139
|
const timerEl = document.getElementById("kwespay-quoteTimer");
|
|
@@ -19167,6 +19154,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19167
19154
|
"kp-quote-timer" +
|
|
19168
19155
|
(secs <= 30 ? " urgent" : "") +
|
|
19169
19156
|
(secs <= 0 ? " expired" : "");
|
|
19157
|
+
|
|
19170
19158
|
if (secs <= 0) {
|
|
19171
19159
|
timerText.textContent = "Refreshing your rate…";
|
|
19172
19160
|
const proceedBtn = document.getElementById("kwespay-proceedToPayment");
|
|
@@ -19175,19 +19163,20 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19175
19163
|
this._loadReviewStep();
|
|
19176
19164
|
}
|
|
19177
19165
|
};
|
|
19166
|
+
|
|
19178
19167
|
update();
|
|
19179
19168
|
this.state.quoteTimerInterval = setInterval(update, 1000);
|
|
19180
|
-
}
|
|
19169
|
+
},
|
|
19181
19170
|
|
|
19182
19171
|
_clearQuoteTimer() {
|
|
19183
19172
|
if (this.state.quoteTimerInterval) {
|
|
19184
19173
|
clearInterval(this.state.quoteTimerInterval);
|
|
19185
19174
|
this.state.quoteTimerInterval = null;
|
|
19186
19175
|
}
|
|
19187
|
-
}
|
|
19188
|
-
|
|
19189
|
-
// ── Payment processing ───────────────────────────────────────────────────────
|
|
19176
|
+
},
|
|
19177
|
+
};
|
|
19190
19178
|
|
|
19179
|
+
const PaymentMethods = {
|
|
19191
19180
|
async _handlePaymentProcessing() {
|
|
19192
19181
|
if (!this.state.currentPayload) {
|
|
19193
19182
|
this._showError(
|
|
@@ -19216,9 +19205,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19216
19205
|
|
|
19217
19206
|
if (!provider) throw new Error("No wallet provider");
|
|
19218
19207
|
|
|
19219
|
-
|
|
19220
|
-
// Must come first — a stale WC session throws on any RPC call, and we want
|
|
19221
|
-
// a clean "reconnect" error rather than a cryptic provider error downstream.
|
|
19208
|
+
|
|
19222
19209
|
const alive = await this.walletService.isSessionAlive();
|
|
19223
19210
|
if (!alive) {
|
|
19224
19211
|
console.error(
|
|
@@ -19232,22 +19219,17 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19232
19219
|
throw err;
|
|
19233
19220
|
}
|
|
19234
19221
|
|
|
19235
|
-
|
|
19222
|
+
|
|
19236
19223
|
if (isMobile) {
|
|
19237
19224
|
document
|
|
19238
19225
|
.getElementById("kwespay-mobileTransactionInstruction")
|
|
19239
19226
|
?.style.setProperty("display", "flex");
|
|
19240
19227
|
}
|
|
19241
19228
|
|
|
19242
|
-
// ── Chain validation ─────────────────────────────────────────────────────
|
|
19243
19229
|
if (strictMobile) {
|
|
19244
|
-
|
|
19245
|
-
// reflects the wallet's actual active chain — always call it live.
|
|
19246
|
-
// Never rely on session namespace account ordering (MetaMask puts
|
|
19247
|
-
// Mainnet first regardless of which chain the user is on).
|
|
19230
|
+
|
|
19248
19231
|
await this._assertMobileChain(provider, targetChainId);
|
|
19249
19232
|
} else {
|
|
19250
|
-
// Desktop / injected — eth_chainId is reliable, switch if needed
|
|
19251
19233
|
const rawChain = await provider.request({ method: "eth_chainId" });
|
|
19252
19234
|
const currentChainId = parseInt(rawChain, 16);
|
|
19253
19235
|
|
|
@@ -19268,21 +19250,17 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19268
19250
|
this.state.selectedToken,
|
|
19269
19251
|
this.state.selectedTokenConfig.decimals
|
|
19270
19252
|
);
|
|
19271
|
-
console.log("[KwesPay] Network switched
|
|
19253
|
+
console.log("[KwesPay] Network switched");
|
|
19272
19254
|
}
|
|
19273
19255
|
}
|
|
19274
19256
|
|
|
19275
|
-
|
|
19276
|
-
// We deep-link to the wallet before the JSON-RPC request lands so the
|
|
19277
|
-
// approval prompt appears immediately without the user having to manually
|
|
19278
|
-
// switch apps.
|
|
19257
|
+
|
|
19279
19258
|
if (strictMobile) {
|
|
19280
19259
|
setStatus(
|
|
19281
19260
|
"Opening your wallet…",
|
|
19282
19261
|
"Approve the payment in your wallet."
|
|
19283
19262
|
);
|
|
19284
19263
|
this.walletService._openWalletForApproval();
|
|
19285
|
-
// Give the OS time to foreground the wallet app before the RPC lands
|
|
19286
19264
|
await new Promise((r) => setTimeout(r, 700));
|
|
19287
19265
|
} else {
|
|
19288
19266
|
setStatus(
|
|
@@ -19291,19 +19269,18 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19291
19269
|
);
|
|
19292
19270
|
}
|
|
19293
19271
|
|
|
19294
|
-
// ── Send transaction ─────────────────────────────────────────────────────
|
|
19295
19272
|
const receipt = await this.paymentService.createPayment({
|
|
19296
19273
|
payload: this.state.currentPayload,
|
|
19297
19274
|
walletProvider: provider,
|
|
19298
19275
|
onStatusUpdate: setStatus,
|
|
19299
19276
|
});
|
|
19300
19277
|
|
|
19301
|
-
|
|
19278
|
+
|
|
19302
19279
|
document
|
|
19303
19280
|
.getElementById("kwespay-mobileTransactionInstruction")
|
|
19304
19281
|
?.style.setProperty("display", "none");
|
|
19305
19282
|
|
|
19306
|
-
|
|
19283
|
+
|
|
19307
19284
|
const decimals = this.state.selectedTokenConfig?.decimals ?? 6;
|
|
19308
19285
|
const amountBig = BigInt(this.state.currentPayload.amountBaseUnits);
|
|
19309
19286
|
const cryptoDisplay = `${formatUnits$1(amountBig, decimals)} ${
|
|
@@ -19366,7 +19343,7 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19366
19343
|
this._showError(title, message);
|
|
19367
19344
|
dispatchWidgetEvent("paymentError", { error: message, errorType });
|
|
19368
19345
|
}
|
|
19369
|
-
}
|
|
19346
|
+
},
|
|
19370
19347
|
|
|
19371
19348
|
/**
|
|
19372
19349
|
* Confirm the wallet is on the target chain before sending a transaction.
|
|
@@ -19374,9 +19351,6 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19374
19351
|
* Throws WRONG_NETWORK if the chain never matches.
|
|
19375
19352
|
*
|
|
19376
19353
|
* MOBILE WC ONLY — never call this on desktop/injected.
|
|
19377
|
-
*
|
|
19378
|
-
* @param {object} provider
|
|
19379
|
-
* @param {number} targetChainId
|
|
19380
19354
|
*/
|
|
19381
19355
|
async _assertMobileChain(provider, targetChainId) {
|
|
19382
19356
|
const MAX_ATTEMPTS = 3;
|
|
@@ -19410,25 +19384,14 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19410
19384
|
}
|
|
19411
19385
|
}
|
|
19412
19386
|
|
|
19413
|
-
// All attempts failed — wallet is on wrong chain
|
|
19414
19387
|
const err = new Error(
|
|
19415
19388
|
`Please switch to ${this.state.selectedNetworkName} in your wallet and try again.`
|
|
19416
19389
|
);
|
|
19417
19390
|
err.code = "WRONG_NETWORK";
|
|
19418
19391
|
throw err;
|
|
19419
|
-
}
|
|
19392
|
+
},
|
|
19393
|
+
|
|
19420
19394
|
|
|
19421
|
-
/**
|
|
19422
|
-
* Switch network for desktop/injected providers and poll until confirmed.
|
|
19423
|
-
* MUST NOT be called in strictMobile mode (mobile WC doesn't support
|
|
19424
|
-
* wallet_switchEthereumChain reliably).
|
|
19425
|
-
*
|
|
19426
|
-
* @param {number} chainId
|
|
19427
|
-
* @param {string} networkName
|
|
19428
|
-
* @param {string} rpcUrl
|
|
19429
|
-
* @param {string} tokenSymbol
|
|
19430
|
-
* @param {number} tokenDecimals
|
|
19431
|
-
*/
|
|
19432
19395
|
async _switchNetworkSafe(
|
|
19433
19396
|
chainId,
|
|
19434
19397
|
networkName,
|
|
@@ -19436,7 +19399,6 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19436
19399
|
tokenSymbol,
|
|
19437
19400
|
tokenDecimals
|
|
19438
19401
|
) {
|
|
19439
|
-
// Capture before any async boundary — prevents `this` loss in callbacks
|
|
19440
19402
|
const switchNetwork = this.walletService.switchNetwork;
|
|
19441
19403
|
const provider = this.walletService.getProvider();
|
|
19442
19404
|
|
|
@@ -19459,12 +19421,11 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19459
19421
|
|
|
19460
19422
|
const targetHex = toHex(chainId);
|
|
19461
19423
|
|
|
19462
|
-
// Check current chain — skip if already correct
|
|
19463
19424
|
try {
|
|
19464
19425
|
const currentHex = toHex(
|
|
19465
19426
|
await provider.request({ method: "eth_chainId" })
|
|
19466
19427
|
);
|
|
19467
|
-
if (currentHex && currentHex === targetHex) return;
|
|
19428
|
+
if (currentHex && currentHex === targetHex) return;
|
|
19468
19429
|
} catch (err) {
|
|
19469
19430
|
console.warn(
|
|
19470
19431
|
"[KwesPay] Could not read chainId before switch:",
|
|
@@ -19472,7 +19433,6 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19472
19433
|
);
|
|
19473
19434
|
}
|
|
19474
19435
|
|
|
19475
|
-
// Issue the switch
|
|
19476
19436
|
try {
|
|
19477
19437
|
await switchNetwork(
|
|
19478
19438
|
chainId,
|
|
@@ -19518,44 +19478,67 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19518
19478
|
`Could not confirm network switch to ${networkName} after 15s. ` +
|
|
19519
19479
|
`Please switch manually in your wallet and try again.`
|
|
19520
19480
|
);
|
|
19521
|
-
}
|
|
19481
|
+
},
|
|
19482
|
+
};
|
|
19483
|
+
|
|
19484
|
+
function resolveAcceptedTokens(input) {
|
|
19485
|
+
if (!input) return null;
|
|
19486
|
+
if (input === "stablecoins") return STABLECOIN_SYMBOLS;
|
|
19487
|
+
if (Array.isArray(input) && input.length)
|
|
19488
|
+
return input.map((t) => t.toUpperCase());
|
|
19489
|
+
return null;
|
|
19490
|
+
}
|
|
19522
19491
|
|
|
19523
|
-
|
|
19492
|
+
class KwesPayWidget {
|
|
19493
|
+
constructor(config) {
|
|
19494
|
+
if (!config.apiKey) throw new Error("[KwesPayWidget] apiKey is required");
|
|
19495
|
+
if (!config.vendorId)
|
|
19496
|
+
throw new Error("[KwesPayWidget] vendorId is required");
|
|
19497
|
+
if (!config.amount || parseFloat(config.amount) <= 0)
|
|
19498
|
+
throw new Error("[KwesPayWidget] Valid amount is required");
|
|
19524
19499
|
|
|
19525
|
-
|
|
19526
|
-
|
|
19527
|
-
|
|
19528
|
-
.
|
|
19529
|
-
|
|
19530
|
-
|
|
19531
|
-
|
|
19500
|
+
this.config = {
|
|
19501
|
+
apiKey: config.apiKey,
|
|
19502
|
+
vendorId: config.vendorId,
|
|
19503
|
+
amount: parseFloat(config.amount),
|
|
19504
|
+
currency: config.currency || DEFAULT_CONFIG.currency,
|
|
19505
|
+
graphqlEndpoint: DEFAULT_CONFIG.graphqlEndpoint,
|
|
19506
|
+
acceptedTokens: resolveAcceptedTokens(config.acceptedTokens),
|
|
19507
|
+
};
|
|
19532
19508
|
|
|
19533
|
-
|
|
19534
|
-
|
|
19535
|
-
|
|
19536
|
-
|
|
19537
|
-
|
|
19538
|
-
targetStep = document.getElementById(`kwespay-step-${stepNumber}`);
|
|
19539
|
-
else targetStep = document.getElementById(`kwespay-step${stepNumber}`);
|
|
19509
|
+
if (!Object.values(SUPPORTED_CURRENCIES).includes(this.config.currency)) {
|
|
19510
|
+
throw new Error(
|
|
19511
|
+
`[KwesPayWidget] Unsupported currency: ${this.config.currency}`
|
|
19512
|
+
);
|
|
19513
|
+
}
|
|
19540
19514
|
|
|
19541
|
-
|
|
19542
|
-
|
|
19543
|
-
|
|
19515
|
+
this.walletService = new WalletService();
|
|
19516
|
+
this.paymentService = new PaymentService$1(
|
|
19517
|
+
this.config.apiKey,
|
|
19518
|
+
this.config.graphqlEndpoint
|
|
19519
|
+
);
|
|
19544
19520
|
|
|
19545
|
-
|
|
19546
|
-
|
|
19547
|
-
|
|
19521
|
+
this.state = {
|
|
19522
|
+
isOpen: false,
|
|
19523
|
+
currentStep: 0,
|
|
19524
|
+
selectedNetwork: null,
|
|
19525
|
+
selectedNetworkName: "",
|
|
19526
|
+
selectedChainId: null,
|
|
19527
|
+
selectedRpcUrl: null,
|
|
19528
|
+
selectedContractAddress: null,
|
|
19529
|
+
selectedToken: null,
|
|
19530
|
+
selectedTokenConfig: null,
|
|
19531
|
+
vendorInfo: null,
|
|
19532
|
+
keyAllowedNetworks: null,
|
|
19533
|
+
keyAllowedTokens: null,
|
|
19534
|
+
currentPayload: null,
|
|
19535
|
+
quoteTimerInterval: null,
|
|
19536
|
+
wcUri: null,
|
|
19537
|
+
};
|
|
19548
19538
|
|
|
19549
|
-
|
|
19550
|
-
const titleEl = document.getElementById("kwespay-errorTitle");
|
|
19551
|
-
const msgEl = document.getElementById("kwespay-errorMessage");
|
|
19552
|
-
if (titleEl) titleEl.textContent = title;
|
|
19553
|
-
if (msgEl) msgEl.textContent = message;
|
|
19554
|
-
this._goToStep(6);
|
|
19539
|
+
this._init();
|
|
19555
19540
|
}
|
|
19556
19541
|
|
|
19557
|
-
// ── Public API ───────────────────────────────────────────────────────────────
|
|
19558
|
-
|
|
19559
19542
|
async open() {
|
|
19560
19543
|
const overlay = document.getElementById("kwespay-widget-overlay");
|
|
19561
19544
|
const container = document.getElementById("kwespay-widget-container");
|
|
@@ -19631,21 +19614,6 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19631
19614
|
return { ...this.state, config: { ...this.config } };
|
|
19632
19615
|
}
|
|
19633
19616
|
|
|
19634
|
-
_reset() {
|
|
19635
|
-
this._clearQuoteTimer();
|
|
19636
|
-
this._removeCustomStep("kwespay-step-wallet-picker");
|
|
19637
|
-
this._removeCustomStep("kwespay-step-wc");
|
|
19638
|
-
this.state.selectedNetwork = null;
|
|
19639
|
-
this.state.selectedNetworkName = "";
|
|
19640
|
-
this.state.selectedChainId = null;
|
|
19641
|
-
this.state.selectedRpcUrl = null;
|
|
19642
|
-
this.state.selectedContractAddress = null;
|
|
19643
|
-
this.state.selectedToken = null;
|
|
19644
|
-
this.state.selectedTokenConfig = null;
|
|
19645
|
-
this.state.currentPayload = null;
|
|
19646
|
-
this.state.wcUri = null;
|
|
19647
|
-
}
|
|
19648
|
-
|
|
19649
19617
|
destroy() {
|
|
19650
19618
|
this._clearQuoteTimer();
|
|
19651
19619
|
document.body.classList.remove("kwespay-open");
|
|
@@ -19660,6 +19628,17 @@ ${e.length}`,n=new TextEncoder().encode(t+e);return "0x"+toString$1(keccak_256$3
|
|
|
19660
19628
|
}
|
|
19661
19629
|
}
|
|
19662
19630
|
|
|
19631
|
+
Object.assign(
|
|
19632
|
+
KwesPayWidget.prototype,
|
|
19633
|
+
DomMethods,
|
|
19634
|
+
NavMethods,
|
|
19635
|
+
APIKeyMethods,
|
|
19636
|
+
NetworkMethods,
|
|
19637
|
+
WalletMethods,
|
|
19638
|
+
QuoteMethods,
|
|
19639
|
+
PaymentMethods
|
|
19640
|
+
);
|
|
19641
|
+
|
|
19663
19642
|
/**
|
|
19664
19643
|
* KwesPay Widget - Main entry point
|
|
19665
19644
|
* @module @kwespay/widget
|