+
No Active Earning
+
+
diff --git a/src/components/wallet/transfer/BulkTransfer.vue b/src/components/wallet/transfer/BulkTransfer.vue
new file mode 100644
index 000000000..1238d9937
--- /dev/null
+++ b/src/components/wallet/transfer/BulkTransfer.vue
@@ -0,0 +1,231 @@
+
+
+
+
+
+ Error: {{ error }}
+
+ Addresses: {{ orders.length }}, Amount: {{ totalBig.toLocaleString() }}
+ {{ asset.symbol }}
+
+
+
+
+
+
+
+
+ {{ $t('transfer.send') }}
+
+
+
+
+
+
+
+
diff --git a/src/components/wallet/transfer/Transfer.vue b/src/components/wallet/transfer/Transfer.vue
new file mode 100644
index 000000000..8cf0c7e65
--- /dev/null
+++ b/src/components/wallet/transfer/Transfer.vue
@@ -0,0 +1,953 @@
+
+
+
+
+
{{ $t('transfer.disconnected') }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/wallet/transfer/types.ts b/src/components/wallet/transfer/types.ts
index b6ec01224..e3bd9bd7f 100644
--- a/src/components/wallet/transfer/types.ts
+++ b/src/components/wallet/transfer/types.ts
@@ -17,3 +17,8 @@ export interface ICurrencyInputDropdownValue {
asset: AvaAsset | null
amount: BN
}
+
+export interface BulkOrder {
+ address: string
+ amount: BN
+}
diff --git a/src/helpers/wallet_helper.ts b/src/helpers/wallet_helper.ts
index 1fd7bd00b..d2f5e9a61 100644
--- a/src/helpers/wallet_helper.ts
+++ b/src/helpers/wallet_helper.ts
@@ -1,5 +1,6 @@
import { ava, bintools } from '@/AVA'
import {
+ buildBulkTransfer,
buildCreateNftFamilyTx,
buildEvmTransferERCNftTx,
buildEvmTransferErc20Tx,
@@ -10,7 +11,7 @@ import { WalletType } from '@/js/wallets/types'
import { AmountOutput } from '@c4tplatform/caminojs/dist/apis/avm'
import { UnsignedTx } from '@c4tplatform/caminojs/dist/apis/platformvm'
-import { ITransaction } from '@/components/wallet/transfer/types'
+import { BulkOrder, ITransaction } from '@/components/wallet/transfer/types'
import { BN, Buffer } from '@c4tplatform/caminojs/dist'
import { UTXO as AVMUTXO } from '@c4tplatform/caminojs/dist/apis/avm/utxos'
import {
@@ -36,6 +37,7 @@ import { GetValidatorsResponse } from '@/store/modules/platform/types'
import { MultisigAliasParams } from '@c4tplatform/caminojs/dist/apis/platformvm'
import { OutputOwners, SignatureError } from '@c4tplatform/caminojs/dist/common'
import { ModelDepositOfferSig } from '@c4tplatform/signavaultjs'
+import AvaAsset from '@/js/AvaAsset'
class WalletHelper {
static async getStake(wallet: WalletType): Promise
{
let addrs = wallet.getAllAddressesP()
@@ -116,6 +118,27 @@ class WalletHelper {
return txId
}
+ static async issueBulkTx(
+ wallet: WalletType,
+ asset: AvaAsset,
+ orders: BulkOrder[],
+ memo: Buffer | undefined
+ ): Promise {
+ const fromAddresses = wallet.getAllAddressesX()
+ const changeAddress = wallet.getChangeAddressAvm()
+
+ let unsignedTx = buildBulkTransfer(
+ fromAddresses,
+ [changeAddress],
+ wallet.getUTXOSet(),
+ orders,
+ asset,
+ memo
+ )
+ const tx = await wallet.signX(unsignedTx)
+ return await ava.XChain().issueTx(tx)
+ }
+
static async validate(
wallet: WalletType,
nodeID: string,
diff --git a/src/js/TxHelper.ts b/src/js/TxHelper.ts
index 3c6d22dba..928576ecd 100644
--- a/src/js/TxHelper.ts
+++ b/src/js/TxHelper.ts
@@ -1,5 +1,5 @@
import { ava, bintools } from '@/AVA'
-import { ITransaction } from '@/components/wallet/transfer/types'
+import { BulkOrder, ITransaction } from '@/components/wallet/transfer/types'
import { BN, Buffer } from '@c4tplatform/caminojs/dist'
import {
AssetAmountDestination,
@@ -13,6 +13,7 @@ import {
UTXOSet,
UTXOSet as AVMUTXOSet,
AVMConstants,
+ SECPTransferOutput,
} from '@c4tplatform/caminojs/dist/apis/avm'
import { PayloadBase } from '@c4tplatform/caminojs/dist/utils'
@@ -26,6 +27,8 @@ import ERCNftToken from '@/js/ERCNftToken'
import { Transaction } from '@ethereumjs/tx'
import { Chain, Common, Hardfork } from '@ethereumjs/common'
import Erc20Token from '@/js/Erc20Token'
+import AvaAsset from './AvaAsset'
+import { ZeroBN } from '@/constants'
export async function buildUnsignedTransaction(
orders: (ITransaction | AVMUTXO)[],
@@ -153,6 +156,59 @@ export async function buildUnsignedTransaction(
return unsignedTx
}
+export function buildBulkTransfer(
+ from: string[],
+ change: string[],
+ utxoset: AVMUTXOSet,
+ orders: BulkOrder[],
+ asset: AvaAsset,
+ memo?: Buffer
+): AVMUnsignedTx {
+ const fromAddrs: Buffer[] = from.map((val) => bintools.parseAddress(val, 'X'))
+ const changeAddrs: Buffer[] = change.map((val) => bintools.parseAddress(val, 'X'))
+
+ const aad: AssetAmountDestination = new AssetAmountDestination([], 0, fromAddrs, changeAddrs, 1)
+ const assetId = bintools.cb58Decode(asset.id)
+ const avaAsset = ava.getNetwork().X.avaxAssetID
+
+ // Collect outputs
+ let amount = ZeroBN
+ orders.forEach((o) => (amount = amount.add(o.amount)))
+ const fee = ava.XChain().getTxFee()
+
+ if (asset.id === avaAsset) {
+ aad.addAssetAmount(assetId, amount, fee)
+ } else {
+ aad.addAssetAmount(assetId, amount, ZeroBN)
+ aad.addAssetAmount(bintools.cb58Decode(avaAsset), ZeroBN, fee)
+ }
+
+ const success: Error = utxoset.getMinimumSpendable(aad)
+
+ let ins: TransferableInput[] = []
+ let outs: TransferableOutput[] = []
+ if (typeof success === 'undefined') {
+ ins = aad.getInputs()
+ outs = aad.getChangeOutputs()
+ } else {
+ throw success
+ }
+
+ // Build the other outputs
+ orders.forEach((v) => {
+ const addr = bintools.parseAddress(v.address, 'X')
+ outs.push(
+ new TransferableOutput(assetId, new SECPTransferOutput(v.amount, [addr], ZeroBN, 1))
+ )
+ })
+
+ let networkId: number = ava.getNetworkID()
+ let chainId: Buffer = bintools.cb58Decode(ava.XChain().getBlockchainID())
+
+ const baseTx = new BaseTx(networkId, chainId, outs, ins, memo)
+
+ return new AVMUnsignedTx(baseTx)
+}
export async function buildCreateNftFamilyTx(
name: string,
symbol: string,
diff --git a/src/locales/en.json b/src/locales/en.json
index ca24eb29e..03d73bb00 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -189,7 +189,10 @@
"label1": "Transaction Hash"
},
"reset": "New Transaction"
- }
+ },
+ "transfer": "Transfer",
+ "receivers": "Receivers and Amounts",
+ "airdrop": "Airdrop"
},
"cross_chain": {
"title": "Cross Chain",
@@ -579,6 +582,11 @@
"deposit_amount": "Deposit Amount",
"deposited_amount": "Deposited Amount"
},
+ "pending_rewards": {
+ "title": "Expired deposit rewards",
+ "description": "At least one deposit has already expired without claiming the full amount of rewards. You can still claim the rewards here.",
+ "pending_reward": "Pending Reward"
+ },
"claim_modal": {
"are_you_sure": "Are you sure you want to claim {amount} {symbol} rewards?",
"note_message": "Transaction fee: {fee} {symbol}.",
diff --git a/src/views/wallet/Earn.vue b/src/views/wallet/Earn.vue
index 0a36435f7..c38ec80ef 100644
--- a/src/views/wallet/Earn.vue
+++ b/src/views/wallet/Earn.vue
@@ -10,7 +10,7 @@
{{ $t('earn.rewards.active_earning.title') }}
-