@windoge98/pnp-phantom
Version:
Phantom wallet adapter for Plug-n-Play
444 lines (443 loc) • 38.7 kB
JavaScript
import { BaseSiwxAdapter, Adapter, deriveAccountId, formatSiwsMessage, createAdapterExtension } from "@windoge98/plug-n-play";
import { formatSiwsMessage as formatSiwsMessage2 } from "@windoge98/plug-n-play";
import { AnonymousIdentity } from "@dfinity/agent";
import { PhantomWalletAdapter } from "@solana/wallet-adapter-phantom";
import { WalletAdapterNetwork, WalletReadyState } from "@solana/wallet-adapter-base";
import { Connection, LAMPORTS_PER_SOL } from "@solana/web3.js";
import { Ed25519KeyIdentity } from "@dfinity/identity";
import bs58 from "bs58";
const idlFactory = ({ IDL }) => {
const RuntimeFeature = IDL.Variant({
"IncludeUriInSeed": IDL.Null,
"DisablePrincipalToSolMapping": IDL.Null,
"DisableSolToPrincipalMapping": IDL.Null
});
IDL.Record({
"uri": IDL.Text,
"runtime_features": IDL.Opt(IDL.Vec(RuntimeFeature)),
"domain": IDL.Text,
"statement": IDL.Opt(IDL.Text),
"scheme": IDL.Opt(IDL.Text),
"salt": IDL.Text,
"session_expires_in": IDL.Opt(IDL.Nat64),
"targets": IDL.Opt(IDL.Vec(IDL.Text)),
"chain_id": IDL.Opt(IDL.Text),
"sign_in_expires_in": IDL.Opt(IDL.Nat64)
});
const Principal = IDL.Vec(IDL.Nat8);
const Address = IDL.Text;
const GetAddressResponse = IDL.Variant({ "Ok": Address, "Err": IDL.Text });
const GetPrincipalResponse = IDL.Variant({
"Ok": Principal,
"Err": IDL.Text
});
const PublicKey = IDL.Vec(IDL.Nat8);
const SessionKey = PublicKey;
const Timestamp = IDL.Nat64;
const Delegation = IDL.Record({
"pubkey": PublicKey,
"targets": IDL.Opt(IDL.Vec(IDL.Principal)),
"expiration": Timestamp
});
const SignedDelegation = IDL.Record({
"signature": IDL.Vec(IDL.Nat8),
"delegation": Delegation
});
const GetDelegationResponse = IDL.Variant({
"Ok": SignedDelegation,
"Err": IDL.Text
});
const SiwsSignature = IDL.Text;
const Nonce = IDL.Text;
const CanisterPublicKey = PublicKey;
const LoginDetails = IDL.Record({
"user_canister_pubkey": CanisterPublicKey,
"expiration": Timestamp
});
const LoginResponse = IDL.Variant({ "Ok": LoginDetails, "Err": IDL.Text });
const SiwsMessage = IDL.Record({
"uri": IDL.Text,
"issued_at": IDL.Nat64,
"domain": IDL.Text,
"statement": IDL.Text,
"version": IDL.Nat32,
"chain_id": IDL.Text,
"address": Address,
"nonce": IDL.Text,
"expiration_time": IDL.Nat64
});
const PrepareLoginResponse = IDL.Variant({
"Ok": SiwsMessage,
"Err": IDL.Text
});
return IDL.Service({
"get_address": IDL.Func([Principal], [GetAddressResponse], ["query"]),
"get_caller_address": IDL.Func([], [GetAddressResponse], ["query"]),
"get_principal": IDL.Func([Address], [GetPrincipalResponse], ["query"]),
"siws_get_delegation": IDL.Func(
[Address, SessionKey, Timestamp],
[GetDelegationResponse],
["query"]
),
"siws_login": IDL.Func(
[SiwsSignature, Address, SessionKey, Nonce],
[LoginResponse],
[]
),
"siws_prepare_login": IDL.Func([Address], [PrepareLoginResponse], [])
});
};
const _PhantomAdapter = class _PhantomAdapter extends BaseSiwxAdapter {
constructor(args) {
super(args);
this.walletName = "Phantom";
this.id = "phantom";
this.phantomAdapter = null;
this.solanaAddress = null;
this.connectingPromise = null;
this.handlePhantomConnect = (publicKey) => {
this.solanaAddress = publicKey.toBase58();
this.logger.debug(`Phantom wallet connected`, { address: this.solanaAddress });
};
this.handlePhantomDisconnect = () => {
if (this.state !== Adapter.Status.DISCONNECTING && this.state !== Adapter.Status.DISCONNECTED) {
this.disconnect();
}
};
this.handlePhantomError = (error) => {
this.logger.error(`Phantom wallet error`, error, {
wallet: this.walletName
});
this.setState(Adapter.Status.ERROR);
this.disconnect();
};
this.id = args.adapter.id;
this.walletName = args.adapter.walletName;
this.logo = args.adapter.logo;
this.config = args.config;
this.initializeConnection();
if (this.isBrowser()) {
this.initializePhantomAdapter();
}
this.setState(Adapter.Status.READY);
}
resolveProviderCanisterId() {
const cfg = this.config;
const canisterId = cfg.providerCanisterId || cfg.siwsProviderCanisterId;
if (!canisterId) {
throw new Error("SIWS provider canister ID not configured.");
}
return String(canisterId);
}
isBrowser() {
return typeof window !== "undefined" && typeof window.document !== "undefined";
}
initializeConnection() {
const network = this.config.solanaNetwork || WalletAdapterNetwork.Mainnet;
const endpoint = this.config.rpcEndpoint || (network === WalletAdapterNetwork.Mainnet ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com");
this.solanaConnection = new Connection(endpoint);
}
initializePhantomAdapter() {
this.phantomAdapter = new PhantomWalletAdapter();
this.setupWalletListeners();
}
setupWalletListeners() {
if (!this.phantomAdapter) return;
this.phantomAdapter.on("connect", this.handlePhantomConnect);
this.phantomAdapter.on("disconnect", this.handlePhantomDisconnect);
this.phantomAdapter.on("error", this.handlePhantomError);
}
removeWalletListeners() {
if (!this.phantomAdapter) return;
this.phantomAdapter.off("connect", this.handlePhantomConnect);
this.phantomAdapter.off("disconnect", this.handlePhantomDisconnect);
this.phantomAdapter.off("error", this.handlePhantomError);
}
destroy() {
this.removeWalletListeners();
}
async isConnected() {
if (!this.phantomAdapter) return false;
return this.phantomAdapter.connected && this.identity !== null && !this.identity.getPrincipal().isAnonymous();
}
async connect() {
if (this.connectingPromise) return this.connectingPromise;
this.connectingPromise = (async () => {
if (!this.isBrowser()) {
throw new Error("Cannot connect to Phantom wallet in non-browser environment");
}
this.resolveProviderCanisterId();
if (this.identity && this.state === Adapter.Status.CONNECTED) {
const principal = this.identity.getPrincipal();
return {
owner: principal.toText(),
subaccount: deriveAccountId(principal)
};
}
this.setState(Adapter.Status.CONNECTING);
try {
if (!this.phantomAdapter) {
this.initializePhantomAdapter();
}
if (!this.phantomAdapter) {
throw new Error("Failed to initialize Phantom adapter");
}
if (!this.phantomAdapter.connected) {
this.logger.debug(`Connecting to Phantom wallet...`);
if (this.phantomAdapter.readyState === WalletReadyState.NotDetected) {
throw new Error("Phantom wallet is not installed. Please install the Phantom browser extension.");
}
try {
await this.phantomAdapter.connect();
} catch (error) {
this.logger.error(`Phantom connection error`, error, {
wallet: this.walletName
});
if (error.name === "WalletWindowClosedError" || error.message?.includes("User rejected the request") || error.message?.includes("Wallet closed")) {
this.setState(Adapter.Status.DISCONNECTED);
throw new Error("Connection cancelled by user");
}
this.setState(Adapter.Status.ERROR);
throw error;
}
}
if (!this.phantomAdapter.publicKey) {
throw new Error("Phantom wallet connected but no public key available");
}
if (!("signMessage" in this.phantomAdapter)) {
throw new Error(`Phantom wallet does not support message signing required for SIWS`);
}
const address = this.phantomAdapter.publicKey.toBase58();
this.solanaAddress = address;
await this.storeExternalAddress(`${this.id}-solana-address`, address);
const { identity, sessionKey } = await this.performSiwsLogin(address, this.phantomAdapter);
this.identity = identity;
this.sessionKey = sessionKey;
const principal = identity.getPrincipal();
this.setState(Adapter.Status.CONNECTED);
return {
owner: principal.toText(),
subaccount: deriveAccountId(principal)
};
} catch (error) {
this.logger.error(`Connect process failed`, error, {
wallet: this.walletName
});
this.setState(Adapter.Status.ERROR);
throw error;
} finally {
this.connectingPromise = null;
}
})();
return this.connectingPromise;
}
async createSiwsProviderActor(identity) {
const id = identity ?? new AnonymousIdentity();
return this.createProviderActor(idlFactory, id);
}
async signSiwsMessage(siwsMessage, adapter) {
const messageText = formatSiwsMessage(siwsMessage);
const messageBytes = new TextEncoder().encode(messageText);
if (!("signMessage" in adapter)) {
throw new Error(`Phantom wallet does not support signMessage.`);
}
const signatureBytes = await adapter.signMessage(messageBytes);
if (signatureBytes instanceof Uint8Array) {
return bs58.encode(signatureBytes);
}
if (signatureBytes instanceof ArrayBuffer) {
return bs58.encode(new Uint8Array(signatureBytes));
}
try {
const arr = Array.isArray(signatureBytes) ? signatureBytes : Object.values(signatureBytes);
return bs58.encode(new Uint8Array(arr));
} catch (e) {
this.logger.error(`Error encoding signature`, e, { wallet: this.walletName });
throw new Error(`Failed to encode signature from Phantom: ${e.message}`);
}
}
async performSiwsLogin(address, adapter) {
const actor = await this.createSiwsProviderActor();
const prepareResult = await actor.siws_prepare_login(address);
if ("Err" in prepareResult) {
throw new Error(`SIWS Prepare Login failed: ${prepareResult.Err}`);
}
const signature = await this.signSiwsMessage(prepareResult.Ok, adapter);
const sessionIdentity = Ed25519KeyIdentity.generate();
const sessionPublicKeyDer = sessionIdentity.getPublicKey().toDer();
const loginResult = await actor.siws_login(
signature,
address,
new Uint8Array(sessionPublicKeyDer),
prepareResult.Ok.nonce
);
if ("Err" in loginResult) {
throw new Error(`SIWS Login failed: ${loginResult.Err}`);
}
const delegationResult = await actor.siws_get_delegation(
address,
new Uint8Array(sessionPublicKeyDer),
loginResult.Ok.expiration
);
if ("Err" in delegationResult) {
throw new Error(`SIWS Get Delegation failed: ${delegationResult.Err}`);
}
const identity = this.createDelegationIdentity(
delegationResult.Ok,
sessionIdentity,
new Uint8Array(loginResult.Ok.user_canister_pubkey).buffer
);
return { identity, sessionKey: sessionIdentity };
}
async disconnectInternal() {
await super.disconnectInternal();
if (this.phantomAdapter) {
try {
if (this.phantomAdapter.connected) {
this.removeWalletListeners();
await this.phantomAdapter.disconnect();
this.setupWalletListeners();
}
} catch (error) {
this.logger.warn(`Error during Phantom disconnect`, {
error,
wallet: this.walletName
});
}
}
this.identity = null;
this.solanaAddress = null;
}
async getPrincipal() {
if (!this.identity) {
throw new Error("Not connected or SIWS flow not completed.");
}
return this.identity.getPrincipal().toText();
}
async getAccountId() {
const principal = await this.getPrincipal();
if (!principal)
throw new Error("Principal not available to derive account ID");
return deriveAccountId(principal);
}
async getSolanaAddress() {
if (!this.solanaAddress) {
throw new Error("Not connected or Solana address not available.");
}
return this.solanaAddress;
}
async getAddresses() {
const principal = this.identity?.getPrincipal();
return {
sol: {
address: this.solanaAddress,
network: this.config.solanaNetwork
},
icp: {
address: principal?.toText(),
subaccount: principal ? deriveAccountId(principal) : void 0
}
};
}
createActorInternal(canisterId, idl, options) {
const requiresSigning = options?.requiresSigning ?? true;
if (requiresSigning && !this.identity) {
throw new Error(
"Cannot create signed actor: Not connected or SIWS flow not completed."
);
}
const agent = this.buildHttpAgentSync({ identity: this.identity ?? void 0 });
return this.createActorWithAgent(agent, canisterId, idl);
}
async getSolBalance() {
if (!this.phantomAdapter?.publicKey) {
throw new Error("Wallet not connected");
}
try {
const balance = await this.solanaConnection.getBalance(this.phantomAdapter.publicKey);
const solAmount = balance / LAMPORTS_PER_SOL;
return { amount: solAmount };
} catch (error) {
this.logger.error(`Failed to get SOL balance`, error, {
wallet: this.walletName
});
throw error;
}
}
async estimateTransactionFee(transaction) {
if (!this.phantomAdapter?.publicKey) {
throw new Error("Wallet not connected");
}
try {
const { blockhash } = await this.solanaConnection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = this.phantomAdapter.publicKey;
const message = transaction.compileMessage();
const fee = await this.solanaConnection.getFeeForMessage(message, "confirmed");
if (fee.value === null) {
throw new Error("Unable to estimate fee");
}
return fee.value / LAMPORTS_PER_SOL;
} catch (error) {
this.logger.error(`Failed to estimate transaction fee`, error, {
wallet: this.walletName
});
throw error;
}
}
async getTransactionStatus(signature) {
try {
const status = await this.solanaConnection.getSignatureStatus(signature);
if (!status.value) {
return { confirmed: false };
}
return {
confirmed: status.value.confirmationStatus === "confirmed" || status.value.confirmationStatus === "finalized",
slot: status.value.slot,
err: status.value.err
};
} catch (error) {
this.logger.error(`Failed to get transaction status`, error, {
wallet: this.walletName,
signature
});
throw error;
}
}
async onStorageRestored(_sessionKey, _delegationChain) {
const storedSolanaAddress = await this.readExternalAddress(`${this.id}-solana-address`);
if (storedSolanaAddress) this.solanaAddress = storedSolanaAddress;
}
async onClearStoredSession() {
this.solanaAddress = null;
await this.storage.remove(`${this.id}-solana-address`);
}
};
_PhantomAdapter.supportedChains = [
Adapter.Chain.ICP,
Adapter.Chain.SOL
];
let PhantomAdapter = _PhantomAdapter;
const phantomLogo = "data:image/webp;base64,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";
const PhantomExtension = createAdapterExtension({
phantom: {
id: "phantom",
enabled: false,
walletName: "Phantom",
logo: phantomLogo,
website: "https://phantom.app",
chain: "SOL",
adapter: PhantomAdapter,
config: {
enabled: false,
solanaNetwork: WalletAdapterNetwork.Mainnet,
// Provider canister ID should be set by the user
siwsProviderCanisterId: ""
}
}
});
export {
PhantomAdapter,
PhantomExtension,
formatSiwsMessage2 as formatSiwsMessage
};