This repository has been archived by the owner on Nov 15, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 145
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from raydium-io/okx-adapter
add okx wallet adapter
- Loading branch information
Showing
2 changed files
with
298 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,296 @@ | ||
import type { EventEmitter, SendTransactionOptions, WalletName } from '@solana/wallet-adapter-base' | ||
import { | ||
BaseMessageSignerWalletAdapter, | ||
isVersionedTransaction, | ||
scopePollingDetectionStrategy, | ||
WalletAccountError, | ||
WalletConnectionError, | ||
WalletDisconnectedError, | ||
WalletDisconnectionError, | ||
WalletError, | ||
WalletNotConnectedError, | ||
WalletNotReadyError, | ||
WalletPublicKeyError, | ||
WalletReadyState, | ||
WalletSendTransactionError, | ||
WalletSignMessageError, | ||
WalletSignTransactionError | ||
} from '@solana/wallet-adapter-base' | ||
import type { | ||
Connection, | ||
SendOptions, | ||
Transaction, | ||
TransactionSignature, | ||
TransactionVersion, | ||
VersionedTransaction | ||
} from '@solana/web3.js' | ||
import { PublicKey } from '@solana/web3.js' | ||
|
||
interface OKXWalletEvents { | ||
connect(...args: unknown[]): unknown | ||
disconnect(...args: unknown[]): unknown | ||
accountChanged(newPublicKey: PublicKey): unknown | ||
} | ||
|
||
interface OKXWallet extends EventEmitter<OKXWalletEvents> { | ||
isOKX?: boolean | ||
publicKey?: { toBytes(): Uint8Array } | ||
isConnected: boolean | ||
signTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T> | ||
signAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]> | ||
signAndSendTransaction<T extends Transaction | VersionedTransaction>( | ||
transaction: T, | ||
options?: SendOptions | ||
): Promise<{ signature: TransactionSignature }> | ||
signMessage(message: Uint8Array): Promise<{ signature: Uint8Array }> | ||
connect(): Promise<void> | ||
disconnect(): Promise<void> | ||
} | ||
|
||
interface OKXWindow extends Window { | ||
okxwallet?: { | ||
isOkxWallet: boolean | ||
solana?: OKXWallet | ||
} | ||
} | ||
|
||
declare const window: OKXWindow | ||
|
||
export const OKXWalletName = 'OKX Wallet' as WalletName<'OKX Wallet'> | ||
|
||
export class OKXWalletAdapter extends BaseMessageSignerWalletAdapter { | ||
name = OKXWalletName | ||
url = 'https://www.okx.com/web3' | ||
icon = | ||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAJDSURBVHgB7Zq9jtpAEMfHlhEgQLiioXEkoAGECwoKxMcTRHmC5E3IoyRPkPAEkI7unJYmTgEFTYwA8a3NTKScLnCHN6c9r1e3P2llWQy7M/s1Gv1twCP0ej37dDq9x+Zut1t3t9vZjDEHIiSRSPg4ZpDL5fxkMvn1cDh8m0wmfugfO53OoFQq/crn8wxfY9EymQyrVCqMfHvScZx1p9ls3pFxXBy/bKlUipGPrVbLuQqAfsCliq3zl0H84zwtjQrOw4Mt1W63P5LvBm2d+Xz+YzqdgkqUy+WgWCy+Mc/nc282m4FqLBYL+3g8fjDxenq72WxANZbLJeA13zDX67UDioL5ybXwafMYu64Ltn3bdDweQ5R97fd7GyhBQMipx4POeEDHIu2LfDdBIGGz+hJ9CQ1ABjoA2egAZPM6AgiCAEQhsi/C4jHyPA/6/f5NG3Ks2+3CYDC4aTccDrn6ojG54MnEvG00GoVmWLIRNZ7wTCwDHYBsdACy0QHIhiuRETxlICWpMMhGZHmqS8qH6JLyGegAZKMDkI0uKf8X4SWlaZo+Pp1bRrwlJU8ZKLIvUjKh0WiQ3sRUbNVq9c5Ebew7KEo2m/1p4jJ4qAmDaqDQBzj5XyiAT4VCQezJigAU+IDU+z8vJFnGWeC+bKQV/5VZ71FV6L7PA3gg3tXrdQ+DgLhC+75Wq3no69P3MC0NFQpx2lL04Ql9gHK1bRDjsSBIvScBnDTk1WrlGIZBorIDEYJj+rhdgnQ67VmWRe0zlplXl81vcyEt0rSoYDUAAAAASUVORK5CYII=' | ||
supportedTransactionVersions: ReadonlySet<TransactionVersion> = new Set(['legacy', 0]) | ||
|
||
private _connecting: boolean | ||
private _wallet: OKXWallet | null | ||
private _publicKey: PublicKey | null | ||
private _readyState: WalletReadyState = | ||
typeof window === 'undefined' || typeof document === 'undefined' | ||
? WalletReadyState.Unsupported | ||
: WalletReadyState.NotDetected | ||
|
||
constructor() { | ||
super() | ||
this._connecting = false | ||
this._wallet = null | ||
this._publicKey = null | ||
|
||
if (this._readyState !== WalletReadyState.Unsupported) { | ||
scopePollingDetectionStrategy(() => { | ||
if (window.okxwallet && window.okxwallet.isOkxWallet && window.okxwallet.solana) { | ||
this._readyState = WalletReadyState.Installed | ||
this.emit('readyStateChange', this._readyState) | ||
return true | ||
} | ||
return false | ||
}) | ||
} | ||
} | ||
|
||
get publicKey() { | ||
return this._publicKey | ||
} | ||
|
||
get connecting() { | ||
return this._connecting | ||
} | ||
|
||
get readyState() { | ||
return this._readyState | ||
} | ||
|
||
async autoConnect(): Promise<void> { | ||
// Skip autoconnect in the Loadable state | ||
// We can't redirect to a universal link without user input | ||
if (this.readyState === WalletReadyState.Installed) { | ||
await this.connect() | ||
} | ||
} | ||
|
||
async connect(): Promise<void> { | ||
try { | ||
if (this.connected || this.connecting) return | ||
|
||
if (this.readyState !== WalletReadyState.Installed) throw new WalletNotReadyError() | ||
|
||
this._connecting = true | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const wallet = window.okxwallet!.solana! | ||
|
||
if (!wallet.isConnected) { | ||
try { | ||
await wallet.connect() | ||
} catch (error: any) { | ||
throw new WalletConnectionError(error?.message, error) | ||
} | ||
} | ||
|
||
if (!wallet.publicKey) throw new WalletAccountError() | ||
|
||
let publicKey: PublicKey | ||
try { | ||
publicKey = new PublicKey(wallet.publicKey.toBytes()) | ||
} catch (error: any) { | ||
throw new WalletPublicKeyError(error?.message, error) | ||
} | ||
|
||
wallet.on('disconnect', this._disconnected) | ||
wallet.on('accountChanged', this._accountChanged) | ||
|
||
this._wallet = wallet | ||
this._publicKey = publicKey | ||
|
||
this.emit('connect', publicKey) | ||
} catch (error: any) { | ||
this.emit('error', error) | ||
throw error | ||
} finally { | ||
this._connecting = false | ||
} | ||
} | ||
|
||
async disconnect(): Promise<void> { | ||
const wallet = this._wallet | ||
if (wallet) { | ||
try { | ||
wallet.off('disconnect', this._disconnected) | ||
wallet.off('accountChanged', this._accountChanged) | ||
} catch { | ||
// emptry | ||
} | ||
|
||
this._wallet = null | ||
this._publicKey = null | ||
|
||
try { | ||
await wallet.disconnect() | ||
} catch (error: any) { | ||
this.emit('error', new WalletDisconnectionError(error?.message, error)) | ||
} | ||
} | ||
|
||
this.emit('disconnect') | ||
} | ||
|
||
async sendTransaction<T extends Transaction | VersionedTransaction>( | ||
transaction: T, | ||
connection: Connection, | ||
options: SendTransactionOptions = {} | ||
): Promise<TransactionSignature> { | ||
try { | ||
const wallet = this._wallet | ||
if (!wallet) throw new WalletNotConnectedError() | ||
|
||
try { | ||
const { signers, ...sendOptions } = options | ||
|
||
if (isVersionedTransaction(transaction)) { | ||
signers?.length && transaction.sign(signers) | ||
} else { | ||
transaction = (await this.prepareTransaction(transaction, connection, sendOptions)) as T | ||
signers?.length && (transaction as Transaction).partialSign(...signers) | ||
} | ||
|
||
sendOptions.preflightCommitment = sendOptions.preflightCommitment || connection.commitment | ||
|
||
const { signature } = await wallet.signAndSendTransaction(transaction, sendOptions) | ||
return signature | ||
} catch (error: any) { | ||
if (error instanceof WalletError) throw error | ||
throw new WalletSendTransactionError(error?.message, error) | ||
} | ||
} catch (error: any) { | ||
this.emit('error', error) | ||
throw error | ||
} | ||
} | ||
|
||
async signTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T> { | ||
try { | ||
const wallet = this._wallet | ||
if (!wallet) throw new WalletNotConnectedError() | ||
|
||
try { | ||
return (await wallet.signTransaction(transaction)) || transaction | ||
} catch (error: any) { | ||
throw new WalletSignTransactionError(error?.message, error) | ||
} | ||
} catch (error: any) { | ||
this.emit('error', error) | ||
throw error | ||
} | ||
} | ||
|
||
async signAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]> { | ||
try { | ||
const wallet = this._wallet | ||
if (!wallet) throw new WalletNotConnectedError() | ||
|
||
try { | ||
return (await wallet.signAllTransactions(transactions)) || transactions | ||
} catch (error: any) { | ||
throw new WalletSignTransactionError(error?.message, error) | ||
} | ||
} catch (error: any) { | ||
this.emit('error', error) | ||
throw error | ||
} | ||
} | ||
|
||
async signMessage(message: Uint8Array): Promise<Uint8Array> { | ||
try { | ||
const wallet = this._wallet | ||
if (!wallet) throw new WalletNotConnectedError() | ||
|
||
try { | ||
const { signature } = await wallet.signMessage(message) | ||
return signature | ||
} catch (error: any) { | ||
throw new WalletSignMessageError(error?.message, error) | ||
} | ||
} catch (error: any) { | ||
this.emit('error', error) | ||
throw error | ||
} | ||
} | ||
|
||
private _disconnected = () => { | ||
const wallet = this._wallet | ||
if (wallet) { | ||
try { | ||
wallet.off('disconnect', this._disconnected) | ||
wallet.off('accountChanged', this._accountChanged) | ||
} catch { | ||
// emptry | ||
} | ||
|
||
this._wallet = null | ||
this._publicKey = null | ||
|
||
this.emit('error', new WalletDisconnectedError()) | ||
this.emit('disconnect') | ||
} | ||
} | ||
|
||
private _accountChanged = (newPublicKey: PublicKey) => { | ||
const publicKey = this._publicKey | ||
if (!publicKey) return | ||
|
||
try { | ||
newPublicKey = new PublicKey(newPublicKey.toBytes()) | ||
} catch (error: any) { | ||
this.emit('error', new WalletPublicKeyError(error?.message, error)) | ||
return | ||
} | ||
|
||
if (publicKey.equals(newPublicKey)) return | ||
|
||
this._publicKey = newPublicKey | ||
this.emit('connect', newPublicKey) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2294490
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
raydium-frontend – ./
raydium-frontend-raydium.vercel.app
raydium-frontend-git-master-raydium.vercel.app
www.raydium.io
raydium.io
raydium-frontend.vercel.app