diff --git a/js/packages/common/src/contexts/wallet.tsx b/js/packages/common/src/contexts/wallet.tsx index 2d3553e..9282f46 100644 --- a/js/packages/common/src/contexts/wallet.tsx +++ b/js/packages/common/src/contexts/wallet.tsx @@ -15,8 +15,8 @@ import { useLocalStorageState } from '../utils/utils'; import { PhantomWalletAdapter } from '../wallet-adapters/phantom'; import { useLocation } from 'react-router'; import { MetaplexModal } from '../components/MetaplexModal'; - import { TorusWalletAdapter } from '../wallet-adapters/torus'; +import { SolflareWalletAdapter } from '../wallet-adapters/solflare'; const ASSETS_URL = 'https://raw.githubusercontent.com/solana-labs/oyster/main/assets/wallets/'; @@ -27,6 +27,12 @@ export const WALLET_PROVIDERS = [ icon: `https://www.phantom.app/img/logo.png`, adapter: PhantomWalletAdapter, }, + { + name: 'Solflare', + url: 'https://solflare.com', + icon: `${ASSETS_URL}solflare.svg`, + adapter: SolflareWalletAdapter, + }, { name: 'Sollet', url: 'https://www.sollet.io', diff --git a/js/packages/common/src/wallet-adapters/solflare/index.tsx b/js/packages/common/src/wallet-adapters/solflare/index.tsx new file mode 100644 index 0000000..018bfab --- /dev/null +++ b/js/packages/common/src/wallet-adapters/solflare/index.tsx @@ -0,0 +1,112 @@ +import EventEmitter from 'eventemitter3'; +import { PublicKey, Transaction } from '@solana/web3.js'; +import { notify } from '../../utils/notifications'; +import { WalletAdapter } from '@solana/wallet-base'; + +interface SolflareWalletEvents { + connect: (...args: unknown[]) => unknown; + disconnect: (...args: unknown[]) => unknown; +} + +interface SolflareWallet extends EventEmitter { + isSolflare?: boolean; + publicKey?: { toBuffer(): Buffer }; + isConnected: boolean; + autoApprove: boolean; + signTransaction: (transaction: Transaction) => Promise; + signAllTransactions: (transactions: Transaction[]) => Promise; + connect: () => Promise; + disconnect: () => Promise; +} + +interface SolflareWindow extends Window { + solflare?: SolflareWallet; +} + +declare const window: SolflareWindow; + +export class SolflareWalletAdapter + extends EventEmitter + implements WalletAdapter { + + _wallet: SolflareWallet | undefined; + _publicKey: PublicKey | undefined; + + constructor() { + super(); + this.connect = this.connect.bind(this); + } + + get connected() { + return !!this._wallet?.isConnected; + } + + get autoApprove() { + return !!this._wallet?.autoApprove; + } + + async signAllTransactions( + transactions: Transaction[], + ): Promise { + if (!this._wallet) { + return transactions; + } + + return this._wallet.signAllTransactions(transactions); + } + + get publicKey() { + if (!this._publicKey && this._wallet?.publicKey) + this._publicKey = new PublicKey( + this._wallet.publicKey.toBuffer(), + ); + + return this._publicKey || null; + } + + async signTransaction(transaction: Transaction) { + if (!this._wallet) { + return transaction; + } + + return this._wallet.signTransaction(transaction); + } + + connect = async () => { + if (this._wallet) { + return; + } + + let wallet: SolflareWallet; + if (window.solflare?.isSolflare) { + wallet = window.solflare; + } else { + window.open('https://solflare.com', '_blank'); + notify({ + message: 'Solflare Error', + description: 'Please install Solflare wallet', + }); + return; + } + + wallet.on('connect', () => { + this._wallet = wallet; + this.emit('connect'); + }); + + if (!wallet.isConnected) { + await wallet.connect(); + } + + this._wallet = wallet; + this.emit('connect'); + }; + + disconnect() { + if (this._wallet) { + this._wallet.disconnect(); + this._wallet = undefined; + this.emit('disconnect'); + } + } +} diff --git a/js/packages/web/src/views/home/index.tsx b/js/packages/web/src/views/home/index.tsx index 1b5dc19..d6a3235 100644 --- a/js/packages/web/src/views/home/index.tsx +++ b/js/packages/web/src/views/home/index.tsx @@ -57,7 +57,9 @@ export const HomeView = () => { if (flag == 1) return true; else return false; }; - const resaleAuctions = auctions.filter(m => checkPrimarySale(m) == true); + const resaleAuctions = auctions + .sort((a, b) => a.auction.info.endedAt?.sub(b.auction.info.endedAt || new BN(0)).toNumber() || 0) + .filter(m => checkPrimarySale(m) == true); // Removed resales from live auctions const liveAuctions = auctions @@ -242,4 +244,4 @@ export const HomeView = () => { ); -}; +}; \ No newline at end of file diff --git a/rust/token-metadata/test/src/main.rs b/rust/token-metadata/test/src/main.rs index 6cfc402..e976b83 100644 --- a/rust/token-metadata/test/src/main.rs +++ b/rust/token-metadata/test/src/main.rs @@ -39,10 +39,15 @@ fn puff_unpuffed_metadata(_app_matches: &ArgMatches, payer: Keypair, client: Rpc let mut needing_puffing = vec![]; for acct in metadata_accounts { if acct.1.data[0] == Key::MetadataV1 as u8 { - let account: Metadata = try_from_slice_unchecked(&acct.1.data).unwrap(); - if account.data.name.len() < MAX_NAME_LENGTH || account.data.uri.len() < MAX_URI_LENGTH || account.data.symbol.len() < MAX_SYMBOL_LENGTH || account.edition_nonce.is_none() { - needing_puffing.push(acct.0); - } + match try_from_slice_unchecked(&acct.1.data) { + Ok(val) => { + let account: Metadata = val; + if account.data.name.len() < MAX_NAME_LENGTH || account.data.uri.len() < MAX_URI_LENGTH || account.data.symbol.len() < MAX_SYMBOL_LENGTH || account.edition_nonce.is_none() { + needing_puffing.push(acct.0); + } + }, + Err(_) => { println!("Skipping {}", acct.0)}, + }; } } println!("Found {} accounts needing puffing", needing_puffing.len()); @@ -52,7 +57,7 @@ fn puff_unpuffed_metadata(_app_matches: &ArgMatches, payer: Keypair, client: Rpc while i < needing_puffing.len() { let pubkey = needing_puffing[i]; instructions.push(puff_metadata_account(spl_token_metadata::id(), pubkey)); - if instructions.len() == 20 { + if instructions.len() >= 20 { let mut transaction = Transaction::new_with_payer(&instructions, Some(&payer.pubkey())); let recent_blockhash = client.get_recent_blockhash().unwrap().0;