@keccak256-evg/passport-sdk
Version:
T-REX Passport SDK for interacting with Passport and Registry contracts
916 lines • 33.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PassportSDK = void 0;
const thirdweb_1 = require("thirdweb");
const constants_1 = require("./constants");
const utils_1 = require("./utils");
class PassportSDK {
constructor(config) {
this.config = config;
this.defaultAccount = config.account;
this.viemClient = (0, utils_1.createViemClient)(config.chain.rpc);
}
/**
* 验证合约配置是否正确
*/
async validateConfiguration() {
const issues = [];
try {
// 验证基本配置
if (!this.config.registryAddress || !this.config.registryAddress.startsWith('0x')) {
issues.push('Invalid registry address format');
}
if (!this.config.chain || !this.config.chain.id) {
issues.push('Invalid chain configuration');
}
if (!this.config.client) {
issues.push('Thirdweb client not configured');
}
// 验证合约是否可访问
try {
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
// 尝试调用一个简单的只读方法
await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "getPassportIdCounter",
params: [],
});
console.log('✅ Registry contract is accessible');
}
catch (contractError) {
issues.push(`Registry contract not accessible: ${contractError}`);
console.error('❌ Registry contract access failed:', contractError);
}
return {
isValid: issues.length === 0,
issues
};
}
catch (error) {
issues.push(`Configuration validation error: ${error}`);
return {
isValid: false,
issues
};
}
}
// Registry 方法
/**
* 创建 Passport
*/
async createPassport(options) {
try {
console.log("createPassport", options);
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
console.log("registryContract", registryContract);
const transaction = (0, thirdweb_1.prepareContractCall)({
contract: registryContract,
method: "createPassport",
params: [],
});
console.log("transaction", transaction);
// 如果指定发送交易,则直接发送
if (options?.sendTransaction) {
const account = options.account || this.defaultAccount;
if (!account) {
throw new Error("Account is required to send transaction");
}
console.log("account", account);
const result = await (0, thirdweb_1.sendTransaction)({
transaction,
account,
});
console.log("result", result);
const receipt = await (0, thirdweb_1.waitForReceipt)({
chain: this.config.chain,
transactionHash: result.transactionHash,
client: this.config.client,
});
return receipt;
}
// 否则返回准备好的交易
return {
preparedTransaction: transaction,
};
}
catch (error) {
console.error("Error preparing create passport transaction:", error);
throw error;
}
}
/**
* 检查钱包是否有 Passport
*/
async checkWalletHasPassport(walletAddress) {
try {
console.log("checkWalletHasPassport", walletAddress);
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
console.log("registryContract", registryContract);
const passportId = await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "walletToPassportId",
params: [walletAddress],
});
console.log("passportId", passportId);
if (passportId === 0n) {
return { hasPassport: false };
}
console.log("passportId", passportId);
const passportAddress = await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "passportIdToContractAddress",
params: [passportId],
});
return {
hasPassport: true,
passportId: Number(passportId),
passportAddress: passportAddress,
};
}
catch (error) {
console.error("Error checking wallet passport:", error);
throw error;
}
}
/**
* 获取 Passport 信息
*/
async getPassportInfo(passportAddress) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const [passportId, boundWallets, walletCount] = await Promise.all([
(0, thirdweb_1.readContract)({
contract: passportContract,
method: "passportId",
params: [],
}),
(0, thirdweb_1.readContract)({
contract: passportContract,
method: "getBoundWallets",
params: [],
}),
(0, thirdweb_1.readContract)({
contract: passportContract,
method: "getWalletCount",
params: [],
}),
]);
return {
passportId: Number(passportId),
passportAddress: passportAddress,
boundWallets: boundWallets,
walletCount: Number(walletCount),
};
}
catch (error) {
console.error("Error getting passport info:", error);
throw error;
}
}
/**
* 预测 Passport 地址
*/
async predictPassportAddress(walletAddress) {
try {
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
const predictedAddress = await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "predictPassportAddress",
params: [walletAddress],
});
return predictedAddress;
}
catch (error) {
console.error("Error predicting passport address:", error);
throw error;
}
}
/**
* 获取 Passport 实现地址
*/
async getPassportImplementation() {
try {
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
const implementation = await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "getPassportImplementation",
params: [],
});
return implementation;
}
catch (error) {
console.error("Error getting passport implementation:", error);
throw error;
}
}
/**
* 获取 Passport ID 计数器
*/
async getPassportIdCounter() {
try {
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
const counter = await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "getPassportIdCounter",
params: [],
});
return Number(counter);
}
catch (error) {
console.error("Error getting passport ID counter:", error);
throw error;
}
}
/**
* 通过 Passport ID 获取合约地址
*/
async getPassportAddressById(passportId) {
try {
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
const passportAddress = await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "passportIdToContractAddress",
params: [BigInt(passportId)],
});
return passportAddress;
}
catch (error) {
console.error("Error getting passport address by ID:", error);
throw error;
}
}
/**
* 检查钱包是否被废除
*/
async isWalletAbolished(walletAddress) {
try {
// 参数验证
if (!walletAddress || !walletAddress.startsWith('0x')) {
throw new Error('Invalid wallet address format');
}
console.log('Checking wallet abolished status for:', walletAddress);
console.log('Registry address:', this.config.registryAddress);
console.log('Chain ID:', this.config.chain.id);
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
const isAbolished = await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "isWalletAbolished",
params: [walletAddress],
});
return Boolean(isAbolished);
}
catch (error) {
console.error("Error checking if wallet is abolished:", error);
console.error("Wallet address:", walletAddress);
console.error("Registry address:", this.config.registryAddress);
// 没有备用方法,isWalletAbolished 是唯一的公开方法
console.error("❌ isWalletAbolished 方法调用失败");
console.error("💡 可能的原因:");
console.error("1. 合约地址不正确");
console.error("2. 网络配置不匹配");
console.error("3. 合约版本不兼容");
console.error("4. RPC 连接问题");
throw error;
}
}
/**
* 检查钱包是否从特定 Passport 解绑
*/
async isWalletUnboundFromPassport(passportId, walletAddress) {
try {
// 参数验证
if (!walletAddress || !walletAddress.startsWith('0x')) {
throw new Error('Invalid wallet address format');
}
if (passportId < 0) {
throw new Error('Invalid passport ID');
}
console.log('Checking wallet unbound status for:', walletAddress, 'from passport ID:', passportId);
console.log('Registry address:', this.config.registryAddress);
console.log('Chain ID:', this.config.chain.id);
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
const isUnbound = await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "isWalletUnboundFromPassport",
params: [BigInt(passportId), walletAddress],
});
return Boolean(isUnbound);
}
catch (error) {
console.error("Error checking if wallet is unbound from passport:", error);
console.error("Wallet address:", walletAddress);
console.error("Passport ID:", passportId);
console.error("Registry address:", this.config.registryAddress);
throw error;
}
}
/**
* 检查钱包是否有特定 Passport
*/
async hasPassport(walletAddress, passportContractAddress) {
try {
const registryContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
const hasPassport = await (0, thirdweb_1.readContract)({
contract: registryContract,
method: "hasPassport",
params: [walletAddress, passportContractAddress],
});
return Boolean(hasPassport);
}
catch (error) {
console.error("Error checking if wallet has passport:", error);
throw error;
}
}
// Passport 方法
/**
* 获取 Passport 当前实现地址
*/
async getPassportImplementationAddress(passportAddress) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const implementation = await (0, thirdweb_1.readContract)({
contract: passportContract,
method: "implementation",
params: [],
});
return implementation;
}
catch (error) {
console.error("Error getting passport implementation address:", error);
throw error;
}
}
/**
* 获取 Passport ID
*/
async getPassportId(passportAddress) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const passportId = await (0, thirdweb_1.readContract)({
contract: passportContract,
method: "passportId",
params: [],
});
return Number(passportId);
}
catch (error) {
console.error("Error getting passport ID:", error);
throw error;
}
}
/**
* 获取 PassportRegistry 合约地址
*/
async getRegistryAddress(passportAddress) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const registry = await (0, thirdweb_1.readContract)({
contract: passportContract,
method: "registry",
params: [],
});
return registry;
}
catch (error) {
console.error("Error getting registry address:", error);
throw error;
}
}
/**
* 检查钱包是否绑定到 Passport
*/
async isWalletBound(passportAddress, walletAddress) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const isBound = await (0, thirdweb_1.readContract)({
contract: passportContract,
method: "isWalletBound",
params: [walletAddress],
});
return Boolean(isBound);
}
catch (error) {
console.error("Error checking if wallet is bound:", error);
throw error;
}
}
/**
* 获取所有绑定钱包
*/
async getBoundWallets(passportAddress) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const boundWallets = await (0, thirdweb_1.readContract)({
contract: passportContract,
method: "getBoundWallets",
params: [],
});
return boundWallets;
}
catch (error) {
console.error("Error getting bound wallets:", error);
throw error;
}
}
/**
* 获取钱包数量
*/
async getWalletCount(passportAddress) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const walletCount = await (0, thirdweb_1.readContract)({
contract: passportContract,
method: "getWalletCount",
params: [],
});
return Number(walletCount);
}
catch (error) {
console.error("Error getting wallet count:", error);
throw error;
}
}
/**
* 通过索引获取绑定钱包
*/
async getBoundWalletByIndex(passportAddress, index) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const wallet = await (0, thirdweb_1.readContract)({
contract: passportContract,
method: "boundWallets",
params: [BigInt(index)],
});
return wallet;
}
catch (error) {
console.error("Error getting bound wallet by index:", error);
throw error;
}
}
/**
* 检查是否有待处理绑定请求
*/
async hasPendingBindRequest(passportAddress, walletAddress) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const hasRequest = await (0, thirdweb_1.readContract)({
contract: passportContract,
method: "hasPendingBindRequest",
params: [walletAddress],
});
return Boolean(hasRequest);
}
catch (error) {
console.error("Error checking if wallet has pending bind request:", error);
throw error;
}
}
/**
* 取消过期的绑定请求
*/
async cancelExpiredBindRequest(passportAddress, walletAddress, options) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const transaction = (0, thirdweb_1.prepareContractCall)({
contract: passportContract,
method: "cancelExpiredBindRequest",
params: [walletAddress],
});
// 如果指定发送交易,则直接发送
if (options?.sendTransaction) {
const account = options.account || this.defaultAccount;
if (!account) {
throw new Error("Account is required to send transaction");
}
const result = await (0, thirdweb_1.sendTransaction)({
transaction,
account,
});
return {
transactionHash: result.transactionHash,
receipt: result,
};
}
// 否则返回准备好的交易
return {
preparedTransaction: transaction,
};
}
catch (error) {
console.error("Error preparing cancel expired bind request transaction:", error);
throw error;
}
}
/**
* 解绑钱包
*/
async unbindWallet(passportAddress, options) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const transaction = (0, thirdweb_1.prepareContractCall)({
contract: passportContract,
method: "unbindWallet",
params: [],
});
// 如果指定发送交易,则直接发送
if (options?.sendTransaction) {
const account = options.account || this.defaultAccount;
if (!account) {
throw new Error("Account is required to send transaction");
}
const result = await (0, thirdweb_1.sendTransaction)({
transaction,
account,
});
return {
transactionHash: result.transactionHash,
receipt: result,
};
}
// 否则返回准备好的交易
return {
preparedTransaction: transaction,
};
}
catch (error) {
console.error("Error preparing unbind wallet transaction:", error);
throw error;
}
}
/**
* 请求绑定钱包
*/
async requestBindWallet(passportAddress, walletAddress, options) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const transaction = (0, thirdweb_1.prepareContractCall)({
contract: passportContract,
method: "requestBindWallet",
params: [walletAddress],
});
// 如果指定发送交易,则直接发送
if (options?.sendTransaction) {
const account = options.account || this.defaultAccount;
if (!account) {
throw new Error("Account is required to send transaction");
}
const result = await (0, thirdweb_1.sendTransaction)({
transaction,
account,
});
const receipt = await (0, thirdweb_1.waitForReceipt)({
chain: this.config.chain,
transactionHash: result.transactionHash,
client: this.config.client,
});
return receipt;
}
// 否则返回准备好的交易
return {
preparedTransaction: transaction,
};
}
catch (error) {
console.error("Error preparing request bind wallet transaction:", error);
throw error;
}
}
/**
* 获取待处理绑定请求信息
*/
async getPendingBindRequest(passportAddress, walletAddress) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const [exists, requester, timestamp, expired] = await (0, thirdweb_1.readContract)({
contract: passportContract,
method: "getPendingBindRequest",
params: [walletAddress],
});
return {
exists: Boolean(exists),
requester: requester,
timestamp: Number(timestamp),
expired: Boolean(expired),
};
}
catch (error) {
console.error("Error getting pending bind request:", error);
throw error;
}
}
/**
* 取消绑定请求
*/
async cancelBindRequest(passportAddress, walletAddress, options) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const transaction = (0, thirdweb_1.prepareContractCall)({
contract: passportContract,
method: "cancelBindRequest",
params: [walletAddress],
});
// 如果指定发送交易,则直接发送
if (options?.sendTransaction) {
const account = options.account || this.defaultAccount;
if (!account) {
throw new Error("Account is required to send transaction");
}
const result = await (0, thirdweb_1.sendTransaction)({
transaction,
account,
});
return {
transactionHash: result.transactionHash,
receipt: result,
};
}
// 否则返回准备好的交易
return {
preparedTransaction: transaction,
};
}
catch (error) {
console.error("Error preparing cancel bind request transaction:", error);
throw error;
}
}
/**
* 接受绑定请求
*/
async acceptBindRequest(passportAddress, options) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const transaction = (0, thirdweb_1.prepareContractCall)({
contract: passportContract,
method: "acceptBindRequest",
params: [],
});
// 如果指定发送交易,则直接发送
if (options?.sendTransaction) {
const account = options.account || this.defaultAccount;
if (!account) {
throw new Error("Account is required to send transaction");
}
const result = await (0, thirdweb_1.sendTransaction)({
transaction,
account,
});
const receipt = await (0, thirdweb_1.waitForReceipt)({
chain: this.config.chain,
transactionHash: result.transactionHash,
client: this.config.client,
});
return receipt;
}
// 否则返回准备好的交易
return {
preparedTransaction: transaction,
};
}
catch (error) {
console.error("Error preparing accept bind request transaction:", error);
throw error;
}
}
/**
* 拒绝绑定请求
*/
async rejectBindRequest(passportAddress, options) {
try {
const passportContract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const transaction = (0, thirdweb_1.prepareContractCall)({
contract: passportContract,
method: "rejectBindRequest",
params: [],
});
// 如果指定发送交易,则直接发送
if (options?.sendTransaction) {
const account = options.account || this.defaultAccount;
if (!account) {
throw new Error("Account is required to send transaction");
}
const result = await (0, thirdweb_1.sendTransaction)({
transaction,
account,
});
return {
transactionHash: result.transactionHash,
receipt: result,
};
}
// 否则返回准备好的交易
return {
preparedTransaction: transaction,
};
}
catch (error) {
console.error("Error preparing reject bind request transaction:", error);
throw error;
}
}
/**
* 获取待处理绑定钱包列表(使用 viem 确保 msg.sender 验证)
*/
async getPendingBindWallets(passportAddress, account) {
return (0, utils_1.getPendingBindWalletsWithViem)(this.viemClient, passportAddress, account);
}
/**
* Check if a Passport needs to be upgraded
* @param passportAddress The Passport contract address
* @returns True if upgrade is needed, false otherwise
*/
async checkPassportUpgrade(passportAddress) {
try {
const contract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: passportAddress,
abi: constants_1.PASSPORT_ABI,
});
const result = await (0, thirdweb_1.readContract)({
contract,
method: "requireUpgrade",
});
return result;
}
catch (error) {
console.error('Error checking passport upgrade:', error);
throw error;
}
}
/**
* Upgrade the caller's Passport to the latest implementation
* @returns Prepared transaction for upgrading the Passport
*/
async upgradeMyPassport(options) {
try {
const contract = (0, thirdweb_1.getContract)({
client: this.config.client,
chain: this.config.chain,
address: this.config.registryAddress,
abi: constants_1.PASSPORT_REGISTRY_ABI,
});
const transaction = await (0, thirdweb_1.prepareContractCall)({
contract,
method: "upgradeMyPassport",
});
// 如果指定发送交易,则直接发送
if (options?.sendTransaction) {
const account = options.account || this.defaultAccount;
if (!account) {
throw new Error("Account is required to send transaction");
}
const result = await (0, thirdweb_1.sendTransaction)({
transaction,
account,
});
return {
transactionHash: result.transactionHash,
receipt: result,
};
}
// 否则返回准备好的交易
return {
preparedTransaction: transaction,
};
}
catch (error) {
console.error('Error preparing upgrade transaction:', error);
throw error;
}
}
}
exports.PassportSDK = PassportSDK;
//# sourceMappingURL=PassportSDK.js.map