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