Skip to content

Commit

Permalink
Chore: sign tx example (#234)
Browse files Browse the repository at this point in the history
* chore: optimize scdo、alephium example

* chore: optimize scdo、alephium call contract example
  • Loading branch information
ByteZhang1024 authored Sep 12, 2024
1 parent 7bae37e commit d846287
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 46 deletions.
95 changes: 93 additions & 2 deletions packages/example/components/chains/alephium/example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import {
} from '@alephium/web3-react';
import { verifySignedMessage } from '@alephium/web3';

import { NodeProvider, TransactionBuilder, buildScriptByteCode, buildContractByteCode, ONE_ALPH, DUST_AMOUNT } from "@alephium/web3"
import { NodeProvider, TransactionBuilder, DUST_AMOUNT } from "@alephium/web3"
import * as fetchRetry from 'fetch-retry'
import { useState } from 'react';
import { RadioGroup, RadioGroupItem } from '../../ui/radio-group';
import { Label } from '../../ui/label';
import { useToast } from '../../ui/use-toast';
import { Input } from '../../ui/input';

// 防止限频
const retryFetch = fetchRetry.default(fetch, {
Expand All @@ -33,6 +34,88 @@ export function Example() {
const balance = useBalance();
const { toast } = useToast();

const getTokenTransferFrom = (chainId: string | undefined, approve: boolean = false) => {
const tokens: {
name: string;
address: string;
}[] = [];

tokens.push({
name: 'USDC',
address: '722954d9067c5a5ad532746a024f2a9d7a18ed9b90e27d0a3a504962160b5600',
});
tokens.push({
name: 'USDT',
address: '556d9582463fe44fbd108aedc9f409f69086dc78d994b88ea6c9e65f8bf98e00',
});

return (
<>
<Input
label="收款地址"
type="text"
name="toAddress"
defaultValue={wallet?.account?.address ?? ''}
/>
<Input label="金额" type="number" name="amount" defaultValue={DUST_AMOUNT.toString()} />

<select name="tokenAddress" className="select">
<option selected value={undefined}>选择 Token</option>
{tokens.map((token) => (
<option value={token.address}>{token.name}</option>
))}
</select>
</>
);
};

const tokenTransferFromToTx = async (fromData: Record<string, any>) => {
const from = wallet?.account?.address ?? '';
const senderPublicKey = wallet?.account?.publicKey ?? '';
const to = fromData.toAddress ?? from;
const amount = fromData.amount;
const tokenAddress = fromData.tokenAddress;

if (!amount) {
return 'Amount is required';
}

const builder = TransactionBuilder.from(nodeUrl)

if (tokenAddress && tokenAddress !== '选择 Token') {

const buildTxResultScript = await builder.buildTransferTx(
{
signerAddress: from,
destinations: [
{ address: to, attoAlphAmount: amount },
]
},
senderPublicKey
)

return JSON.stringify({
unsignedTx: buildTxResultScript.unsignedTx,
signerAddress: from,
})
}

const buildTxResultScript = await builder.buildTransferTx(
{
signerAddress: from,
destinations: [
{ address: to, attoAlphAmount: DUST_AMOUNT, tokens: [{ id: tokenAddress, amount: amount }] },
]
},
senderPublicKey
)

return JSON.stringify({
unsignedTx: buildTxResultScript.unsignedTx,
signerAddress: from,
})
}

return (
<>
<AlephiumConnectButton />
Expand Down Expand Up @@ -74,7 +157,11 @@ export function Example() {
allowCallWithoutProvider={!!wallet}
presupposeParams={params.signAndSubmitDeployContractTx(wallet?.account?.address ?? '')}
onExecute={async (request: string) => {
return wallet.signer.signAndSubmitDeployContractTx(JSON.parse(request));
console.log('xxx=====>>>>>>> 1');
const xxx = await wallet.signer.signAndSubmitDeployContractTx(JSON.parse(request));
console.log('xxx=====>>>>>>> 2', xxx);

return xxx;
}}
/>
<ApiPayload
Expand All @@ -91,6 +178,8 @@ export function Example() {
description=""
allowCallWithoutProvider={!!wallet}
presupposeParams={params.signAndSubmitUnsignedTx(wallet?.account?.address ?? '')}
generateRequestFrom={() => getTokenTransferFrom(wallet?.account?.address ?? '')}
onGenerateRequest={tokenTransferFromToTx}
onExecute={async (request: string) => {
return wallet.signer.signAndSubmitUnsignedTx(JSON.parse(request));
}}
Expand All @@ -100,6 +189,8 @@ export function Example() {
description=""
allowCallWithoutProvider={!!wallet}
presupposeParams={params.signUnsignedTx(wallet?.account?.address ?? '')}
generateRequestFrom={() => getTokenTransferFrom(wallet?.account?.address ?? '')}
onGenerateRequest={tokenTransferFromToTx}
onExecute={async (request: string) => {
return wallet.signer.signUnsignedTx(JSON.parse(request));
}}
Expand Down
5 changes: 3 additions & 2 deletions packages/example/components/chains/alephium/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,10 @@ export default {
{
id: 'signAndSubmitDeployContractTx-test',
name: 'Deploy test contract',
description: 'Deploy test contract 最少需要 0.1 ALPH',
value: JSON.stringify({
signerAddress: from,
bytecode: '000117010100000004d362d46012b413c40de0b6b3a7640000a90000',
bytecode: '000110010001010105d3eb23039a16000e2c020000',
}),
},
];
Expand All @@ -97,7 +98,7 @@ export default {
value: JSON.stringify({
signerAddress: from,
bytecode:
'01010300000007b413c40de0b6b3a7640000a20c0c1440206c3b1f6262ffad9a4cb1e78f03f17f3593837505a69edbc18a59cf23c1f1c4020100',
'0101030001000d13020d0d144020c3fb9f552e7ab1138023ef0e313cf43483fc7fa35f2bbadc3f997ab17e52a10001001700160013020e2c2f0c7b',
}),
},
];
Expand Down
147 changes: 124 additions & 23 deletions packages/example/components/chains/scdo/example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import DappList from '../../../components/DAppList';
import params from './params';
import { Input } from '../../ui/input';
import { ScdoNodeClient } from './rpc';
import BigNumber from 'bignumber.js';
import { useToast } from '../../ui/use-toast';
import { encodeTokenTransferPayload } from './utils';

// https://demo.scdo.org/
export default function Example() {
Expand All @@ -30,6 +33,7 @@ export default function Example() {
const client = new ScdoNodeClient();

const { account, provider } = useWallet<IProviderApi>();
const { toast } = useToast();

const onConnectWallet = async (selectedWallet: IKnownWallet) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
Expand All @@ -49,6 +53,16 @@ export default function Example() {
};

const getTokenTransferFrom = (chainId: string | undefined, approve: boolean = false) => {
const tokens: {
name: string;
address: string;
}[] = [];

tokens.push({
name: 'Test Token',
address: '1S015daca201b66f96f74b4230916f9db8db0c0002',
});

return (
<>
<Input
Expand All @@ -71,10 +85,54 @@ export default function Example() {
</div>
</>
)}

<select name="tokenAddress" className="select">
<option selected value={undefined}>选择 Token</option>
{tokens.map((token) => (
<option value={token.address}>{token.name}</option>
))}
</select>
</>
);
};

const tokenTransferFromToTx = async (fromData: Record<string, any>) => {
const from = account?.address ?? '';
const to = fromData.toAddress ?? from;
const amount = fromData.amount;
const tokenAddress = fromData.tokenAddress;

if (!amount) {
return 'Amount is required';
}

const nonce = await client.getNonce(from);

if (tokenAddress && tokenAddress !== '选择 Token') {
const payload = encodeTokenTransferPayload({ address: to, amount });

return JSON.stringify({
accountNonce: nonce,
from: from,
to: tokenAddress,
amount: 0,
gasLimit: 100000,
gasPrice: 1,
payload: payload,
});
}

return JSON.stringify({
accountNonce: nonce,
from: from,
to: to,
amount: new BigNumber(amount).toNumber(),
gasLimit: 21000,
gasPrice: 1,
payload: '',
});
}

return (
<>
<ConnectButton<IProviderApi>
Expand Down Expand Up @@ -154,14 +212,52 @@ export default function Example() {
<ApiPayload
title="scdo_estimateGas"
description="估算交易费用"
presupposeParams={params.estimateGas(account?.address ?? '', account?.address ?? '')}
presupposeParams={params.signTransaction(account?.address ?? '', account?.address ?? '')}
generateRequestFrom={() => getTokenTransferFrom(account?.chainId)}
onGenerateRequest={tokenTransferFromToTx}
onExecute={async (request: string) => {
const tx = JSON.parse(request);
return await provider?.request<string>({
method: 'scdo_estimateGas',
method: 'scdo_signTransaction',
params: [tx],
});
}}
onValidate={async (request: string, response: string) => {
const res = JSON.parse(response) as {
"Data": {
"Type": number,
"From": string,
"To": string,
"Amount": number,
"AccountNonce": number,
"GasPrice": number,
"GasLimit": number,
"Timestamp": number,
"Payload": string
},
"Hash": string,
"Signature": {
"Sig": string
}
}
return await provider?.request<string>({
method: 'scdo_estimateGas',
params: [{
'accountNonce': res.Data.AccountNonce,
'amount': res.Data.Amount,
'from': res.Data.From,
'to': res.Data.To,
'gasLimit': res.Data.GasLimit,
'gasPrice': res.Data.GasPrice,
'hash': res.Hash,
'payload': res.Data.Payload,
'signature': {
'Sig': res.Signature.Sig,
},

}],
});
}}
/>
<ApiPayload
title="scdo_signTransaction"
Expand All @@ -174,33 +270,38 @@ export default function Example() {
params: [tx],
});
}}
generateRequestFrom={() => getTokenTransferFrom(account?.chainId)}
onGenerateRequest={async (fromData: Record<string, any>) => {
const from = account?.address ?? '';
const to = fromData.toAddress ?? from;
const amount = fromData.amount;

if (!amount) {
return 'Amount is required';
onValidate={async (request: string, response: string) => {
const tx = JSON.parse(response);
const success = await client.pushTransaction(account?.address ?? '', tx);
if (!success) {
toast({
title: '广播交易失败',
description: '请检查交易是否正确',
variant: 'destructive',
});
}

const nonce = await client.getNonce(from);
console.log('nonce', nonce);

return JSON.stringify({
accountNonce: nonce,
from: from,
to: to,
amount: amount,
gasLimit: 21000,
gasPrice: 1,
payload: '',
return success;
}}
generateRequestFrom={() => getTokenTransferFrom(account?.chainId)}
onGenerateRequest={tokenTransferFromToTx}
/>
<ApiPayload
title="scdo_sendTransaction"
description="发送交易,动态生成"
presupposeParams={params.signTransaction(account?.address ?? '', account?.address ?? '')}
generateRequestFrom={() => getTokenTransferFrom(account?.chainId)}
onGenerateRequest={tokenTransferFromToTx}
onExecute={async (request: string) => {
const tx = JSON.parse(request);
return await provider?.request<string>({
method: 'scdo_sendTransaction',
params: [tx],
});
}}
/>
<ApiPayload
title="scdo_sendTransaction"
description="发送交易"
description="发送交易,静态参数"
presupposeParams={params.sendTransaction(account?.address ?? '', account?.address ?? '')}
onExecute={async (request: string) => {
const tx = JSON.parse(request);
Expand Down
Loading

0 comments on commit d846287

Please sign in to comment.