@worldcoin/minikit-js
Version:
minikit-js is our SDK for building mini-apps.
363 lines (355 loc) • 11.9 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/wagmi-fallback-register.ts
var wagmi_fallback_register_exports = {};
__export(wagmi_fallback_register_exports, {
registerWagmiFallback: () => registerWagmiFallback
});
module.exports = __toCommonJS(wagmi_fallback_register_exports);
// src/global-keys.ts
var WAGMI_CONFIG_KEY = "__minikit_wagmi_config__";
var WAGMI_INSTALL_HOOK_KEY = "__minikit_install_wagmi_fallback__";
// src/helpers/hex.ts
var HEX_ADDRESS_REGEX = /^0x[0-9a-fA-F]{40}$/;
var HEX_STRING_REGEX = /^0x[0-9a-fA-F]*$/;
function isHexAddress(value) {
return typeof value === "string" && HEX_ADDRESS_REGEX.test(value);
}
function isHexString(value) {
return typeof value === "string" && HEX_STRING_REGEX.test(value);
}
// src/commands/fallback.ts
var PartialExecutionError = class extends Error {
constructor(message, submitted, cause) {
super(message);
this.name = "PartialExecutionError";
this.submitted = submitted;
this.cause = cause;
}
};
// src/commands/fallback-adapter-registry.ts
var FALLBACK_ADAPTER_KEY = "__minikit_fallback_adapter__";
function setFallbackAdapter(adapter) {
globalThis[FALLBACK_ADAPTER_KEY] = adapter;
}
// src/commands/wagmi-fallback.ts
var SIWE_NONCE_REGEX = /^[a-zA-Z0-9]{8,}$/;
function setWagmiConfig(config) {
globalThis[WAGMI_CONFIG_KEY] = config;
registerWagmiFallbacks();
}
globalThis[WAGMI_INSTALL_HOOK_KEY] = setWagmiConfig;
function getWagmiConfig() {
return globalThis[WAGMI_CONFIG_KEY];
}
function registerWagmiFallbacks() {
setFallbackAdapter({
walletAuth: wagmiWalletAuth,
signMessage: wagmiSignMessage,
signTypedData: wagmiSignTypedData,
sendTransaction: wagmiSendTransaction
});
}
async function loadWagmiActions() {
try {
return await import("wagmi/actions");
} catch (error) {
const wrappedError = new Error(
'Wagmi fallback requires the "wagmi" package. Install wagmi or provide a custom fallback.'
);
wrappedError.cause = error;
throw wrappedError;
}
}
async function loadSiwe() {
try {
return await import("siwe");
} catch (error) {
const wrappedError = new Error(
'Wagmi walletAuth fallback requires the "siwe" package. Install siwe or provide a custom fallback.'
);
wrappedError.cause = error;
throw wrappedError;
}
}
async function checksumAddress(addr) {
try {
const { getAddress } = await import("viem");
return getAddress(addr);
} catch {
return addr;
}
}
async function ensureConnected(config) {
const { connect, getConnections } = await loadWagmiActions();
const isWorldApp = typeof window !== "undefined" && Boolean(window.WorldApp);
const existingConnection = getConnections(config).find(
(connection) => connection.accounts && connection.accounts.length > 0 && (isWorldApp || connection.connector?.id !== "worldApp")
);
if (existingConnection && existingConnection.accounts) {
return {
address: await checksumAddress(existingConnection.accounts[0]),
connector: existingConnection.connector
};
}
const connectors = config.connectors;
if (!connectors || connectors.length === 0) {
throw new Error("No Wagmi connectors configured");
}
const candidateConnectors = isWorldApp ? connectors : connectors.filter(
(connector) => connector.id !== "worldApp"
);
if (!isWorldApp && candidateConnectors.length === 0) {
throw new Error(
"No web Wagmi connectors configured. Add a web connector (e.g. injected or walletConnect) after worldApp()."
);
}
const selectedConnector = candidateConnectors[0];
try {
const result = await connect(config, { connector: selectedConnector });
if (result.accounts.length > 0) {
const account = result.accounts[0];
const address = typeof account === "string" ? account : account.address;
if (address) {
return {
address: await checksumAddress(address),
connector: selectedConnector
};
}
}
} catch (error) {
const connectorId = selectedConnector.id ?? "unknown";
const wrappedError = new Error(
`Failed to connect with connector "${connectorId}". Reorder connectors to change the default connector.`
);
wrappedError.cause = error;
throw wrappedError;
}
throw new Error("Failed to connect wallet");
}
async function wagmiWalletAuth(params) {
const config = getWagmiConfig();
if (!config) {
throw new Error(
"Wagmi config not available. Pass wagmiConfig to MiniKitProvider."
);
}
const { signMessage } = await loadWagmiActions();
const { SiweMessage } = await loadSiwe();
const { address, connector } = await ensureConnected(config);
if (!SIWE_NONCE_REGEX.test(params.nonce)) {
throw new Error(
"Invalid nonce: must be alphanumeric and at least 8 characters (EIP-4361)"
);
}
const siweMessage = new SiweMessage({
domain: typeof window !== "undefined" ? window.location.host : "localhost",
address,
statement: params.statement,
uri: typeof window !== "undefined" ? window.location.origin : "http://localhost",
version: "1",
chainId: 480,
// World Chain
nonce: params.nonce,
expirationTime: params.expirationTime?.toISOString()
});
const message = siweMessage.prepareMessage();
const signature = await signMessage(config, {
connector,
account: address,
message
});
return {
address,
message,
signature
};
}
async function wagmiSignMessage(params) {
const config = getWagmiConfig();
if (!config) {
throw new Error(
"Wagmi config not available. Pass wagmiConfig to MiniKitProvider."
);
}
const { signMessage } = await loadWagmiActions();
const { address, connector } = await ensureConnected(config);
const signature = await signMessage(config, {
connector,
account: address,
message: params.message
});
return {
status: "success",
version: 1,
signature,
address
};
}
async function wagmiSignTypedData(params) {
const config = getWagmiConfig();
if (!config) {
throw new Error(
"Wagmi config not available. Pass wagmiConfig to MiniKitProvider."
);
}
const { getChainId, signTypedData, switchChain } = await loadWagmiActions();
const { address, connector } = await ensureConnected(config);
if (params.chainId !== void 0) {
const currentChainId = await getChainId(config);
if (currentChainId !== params.chainId) {
await switchChain(config, { chainId: params.chainId, connector });
}
}
const signature = await signTypedData(config, {
connector,
account: address,
types: params.types,
primaryType: params.primaryType,
domain: params.domain,
message: params.message
});
return {
status: "success",
version: 1,
signature,
address
};
}
function isChainMismatchError(error) {
const message = error instanceof Error ? error.message : String(error);
return message.includes("does not match the target chain");
}
function validateBatch(transactions) {
return transactions.map((tx, i) => {
if (!isHexAddress(tx.address)) {
throw new Error(
`Transaction ${i + 1}: invalid address "${tx.address}". Must be a 0x-prefixed 20-byte hex string.`
);
}
if (tx.data !== void 0 && !isHexString(tx.data)) {
throw new Error(
`Transaction ${i + 1}: invalid data "${tx.data}". Must be a 0x-prefixed hex string.`
);
}
let value;
if (tx.value !== void 0 && tx.value !== "") {
try {
value = BigInt(tx.value);
} catch {
throw new Error(
`Transaction ${i + 1}: invalid value "${tx.value}". Must be a decimal or hex string parseable as BigInt.`
);
}
if (value < 0n) {
throw new Error(
`Transaction ${i + 1}: value cannot be negative (got "${tx.value}").`
);
}
}
return {
to: tx.address,
...tx.data !== void 0 ? { data: tx.data } : {},
...value !== void 0 ? { value } : {}
};
});
}
async function wagmiSendTransaction(params) {
if (params.transactions.length === 0) {
throw new Error("At least one transaction is required");
}
const normalizedTxs = validateBatch(params.transactions);
const config = getWagmiConfig();
if (!config) {
throw new Error(
"Wagmi config not available. Pass wagmiConfig to MiniKitProvider."
);
}
const { getChainId, getWalletClient, sendTransaction, switchChain } = await loadWagmiActions();
const { address, connector } = await ensureConnected(config);
const targetChainId = params.chainId ?? config.chains?.[0]?.id;
const ensureTargetChain = async () => {
if (targetChainId === void 0) return;
const currentChainId = await getChainId(config);
if (currentChainId !== targetChainId) {
await switchChain(config, { chainId: targetChainId, connector });
}
const walletClient = await getWalletClient(config);
const providerChainId = walletClient ? await walletClient.getChainId() : await getChainId(config);
if (providerChainId !== targetChainId) {
throw new Error(
`Wallet network mismatch: expected chain ${targetChainId}, got ${providerChainId}. Please switch networks in your wallet and retry.`
);
}
};
await ensureTargetChain();
const sendWithChainRetry = async (tx) => {
const send = () => sendTransaction(config, {
connector,
account: address,
chainId: targetChainId,
to: tx.to,
data: tx.data,
value: tx.value
});
try {
return await send();
} catch (error) {
if (targetChainId !== void 0 && isChainMismatchError(error)) {
await ensureTargetChain();
return await send();
}
throw error;
}
};
const submitted = [];
for (let i = 0; i < normalizedTxs.length; i++) {
try {
submitted.push(await sendWithChainRetry(normalizedTxs[i]));
} catch (error) {
if (submitted.length > 0) {
throw new PartialExecutionError(
`Transaction ${i + 1}/${normalizedTxs.length} failed after ${submitted.length} tx(s) were already submitted. Resolve manually.`,
submitted,
error
);
}
throw error;
}
}
return { transactionHash: submitted[submitted.length - 1] };
}
// src/wagmi-fallback-register.ts
function registerWagmiFallback(config) {
setWagmiConfig(config);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
registerWagmiFallback
});