Skip to content

Commit

Permalink
feat: add max button feature for solana send flow
Browse files Browse the repository at this point in the history
  • Loading branch information
zoruka committed Sep 10, 2024
1 parent 6db04c3 commit 01a7acc
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 12 deletions.
35 changes: 31 additions & 4 deletions packages/base/adapters/solana/web3js/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,16 +184,29 @@ export class SolanaWeb3JsClient implements ChainAdapter<SolStoreUtilState, CaipN
return new TextDecoder().decode(signature)
},

estimateGas: async () => {
estimateGas: async params => {
if (params.chainNamespace !== 'solana') {
throw new Error('Chain namespace is not supported')
}

const connection = SolStoreUtil.state.connection

if (!connection) {
throw new Error('Connection is not set')
}

const recentBlockhash = await connection.getRecentBlockhash()
const provider = this.getProvider()

const transaction = await createSendTransaction({
provider,
connection,
to: '11111111111111111111111111111111',
value: 1
})

const fee = await transaction.getEstimatedFee(connection)

return BigInt(recentBlockhash.feeCalculator.lamportsPerSignature)
return BigInt(fee || 0)
},
// -- Transaction methods ---------------------------------------------------
/**
Expand All @@ -213,8 +226,9 @@ export class SolanaWeb3JsClient implements ChainAdapter<SolStoreUtilState, CaipN
}

const connection = SolStoreUtil.state.connection
const address = SolStoreUtil.state.address

if (!connection) {
if (!connection || !address) {
throw new Error('Connection is not set')
}

Expand All @@ -229,6 +243,19 @@ export class SolanaWeb3JsClient implements ChainAdapter<SolStoreUtilState, CaipN

const result = await provider.sendTransaction(transaction, connection)

await new Promise<void>(resolve => {
const interval = setInterval(async () => {
const status = await connection.getSignatureStatus(result)

if (status?.value) {
clearInterval(interval)
resolve()
}
}, 1000)
})

await this.syncBalance(address)

return result
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
SystemProgram,
type Connection,
Transaction,
LAMPORTS_PER_SOL
LAMPORTS_PER_SOL,
ComputeBudgetProgram
} from '@solana/web3.js'
import type { Provider } from '@web3modal/scaffold-utils/solana'

Expand All @@ -30,6 +31,8 @@ export async function createSendTransaction({
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash()

const instructions = [
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 20000000 }),
ComputeBudgetProgram.setComputeUnitLimit({ units: 500 }),
SystemProgram.transfer({
fromPubkey: provider.publicKey,
toPubkey,
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/controllers/SendController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@ export const SendController = {
to: this.state.receiverAddress,
value: this.state.sendTokenAmount
})
.then(() => {
this.resetSend()
AccountController.fetchTokenBalance()
})
.catch(error => {
SnackController.showError('Failed to send transaction. Please try again.')
// eslint-disable-next-line no-console
console.error('SendController:sendToken - failed to send solana transaction', error)
})

return
default:
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/controllers/SwapController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ export const SwapController = {
case 'solana':
state.gasFee = res.standard
state.gasPriceInUSD = NumberUtil.multiply(res.standard, state.networkPrice)
.dividedBy(10 ** 9)
.dividedBy(1e9)
.toNumber()

return {
Expand Down
14 changes: 8 additions & 6 deletions packages/scaffold-ui/src/partials/w3m-input-token/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export class W3mInputToken extends LitElement {

@property({ type: Number }) public gasPriceInUSD?: number

@property({ type: Number }) public gasPrice?: number

// -- Render -------------------------------------------- //
public override render() {
return html` <wui-flex
Expand Down Expand Up @@ -112,19 +114,19 @@ export class W3mInputToken extends LitElement {
}

private onMaxClick() {
if (this.token && this.gasPriceInUSD) {
const amountOfTokenGasRequires = NumberUtil.bigNumber(
this.gasPriceInUSD.toFixed(5)
).dividedBy(this.token.price)

if (this.token && typeof this.gasPrice !== 'undefined') {
const isNetworkToken =
this.token.address === undefined ||
Object.values(ConstantsUtil.NATIVE_TOKEN_ADDRESS).some(
nativeAddress => this.token?.address === nativeAddress
)

const numericGas = NumberUtil.bigNumber(this.gasPrice).shiftedBy(
-this.token.quantity.decimals
)

const maxValue = isNetworkToken
? NumberUtil.bigNumber(this.token.quantity.numeric).minus(amountOfTokenGasRequires)
? NumberUtil.bigNumber(this.token.quantity.numeric).minus(numericGas)
: NumberUtil.bigNumber(this.token.quantity.numeric)

SendController.setTokenAmount(Number(maxValue.toFixed(20)))
Expand Down
3 changes: 3 additions & 0 deletions packages/scaffold-ui/src/views/w3m-wallet-send-view/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export class W3mWalletSendView extends LitElement {

@state() private gasPriceInUSD = SendController.state.gasPriceInUSD

@state() private gasPrice = SendController.state.gasPrice

@state() private message:
| 'Preview Send'
| 'Select Token'
Expand Down Expand Up @@ -70,6 +72,7 @@ export class W3mWalletSendView extends LitElement {
.token=${this.token}
.sendTokenAmount=${this.sendTokenAmount}
.gasPriceInUSD=${this.gasPriceInUSD}
.gasPrice=${this.gasPrice}
></w3m-input-token>
<wui-icon-box
size="inherit"
Expand Down

0 comments on commit 01a7acc

Please sign in to comment.