Skip to content

Commit

Permalink
generate wallet per user in lending bot
Browse files Browse the repository at this point in the history
  • Loading branch information
pragmaxim committed Oct 6, 2024
1 parent 2729e03 commit 9feb212
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 24 deletions.
48 changes: 24 additions & 24 deletions test/lending.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,16 @@ import {
} from '@alephium/web3'
import { testNodeWallet } from '@alephium/web3-test'
import { PrivateKeyWallet, deriveHDWalletPrivateKeyForGroup } from '@alephium/web3-wallet'
import * as bip39 from 'bip39'

class LendingBot {
private readonly nodeProvider: NodeProvider // This can be initialized with node url + api key in a real application
private readonly mnemonic: string // This should be stored securely in a real application
readonly userGroups: Map<string, number>
readonly userWallets: Map<string, PrivateKeyWallet>

constructor(nodeProvider: NodeProvider, mnemonic: string) {
constructor(nodeProvider: NodeProvider) {
this.nodeProvider = nodeProvider
this.mnemonic = mnemonic
this.userGroups = new Map()
this.userWallets = new Map()
}

addUser(userId: string): PrivateKeyWallet {
Expand All @@ -47,7 +46,9 @@ class LendingBot {
}

const groupNumber = this.userGroups.size
const wallet = PrivateKeyWallet.Random(groupNumber, this.nodeProvider)
this.userGroups.set(userId, groupNumber)
this.userWallets.set(userId, wallet)
return this.getUserWallet(userId)
}

Expand All @@ -56,9 +57,11 @@ class LendingBot {
if (groupNumber === undefined) {
throw new Error(`User ${userId} does not exist`)
}

const [privateKey, _] = deriveHDWalletPrivateKeyForGroup(this.mnemonic, groupNumber, 'default')
return new PrivateKeyWallet({ privateKey, nodeProvider: this.nodeProvider })
const wallet = this.userWallets.get(userId)
if (wallet === undefined) {
throw new Error(`User ${userId} wallet does not exist`)
}
return wallet as PrivateKeyWallet
}

getUserAddress(userId: string) {
Expand All @@ -73,16 +76,14 @@ class LendingBot {
params,
await signer.getPublicKey(params.signerAddress)
)
const signedTxResults = await Promise.all(
return await Promise.all(
buildTxResults.map(async (tx) => {
const signature = await signer.signRaw(params.signerAddress, tx.txId)
return { ...tx, signature }
return await signer.signAndSubmitUnsignedTx({
signerAddress: params.signerAddress,
unsignedTx: tx.unsignedTx
})
})
)
for (const signedTx of signedTxResults) {
await signer.submitTransaction(signedTx)
}
return signedTxResults
}

async getUserBalance(userId: string) {
Expand All @@ -92,32 +93,33 @@ class LendingBot {
}

async distributeWealth(users: string[], deposit: bigint) {
const testWallet = await testNodeWallet()
const signerAddress = (await testWallet.getSelectedAccount()).address
const signer = await testNodeWallet()
const signerAddress = (await signer.getSelectedAccount()).address

const destinations = users.map((user) => ({
address: this.addUser(user).address,
attoAlphAmount: deposit
}))

await this.signAndSubmitMultiGroupTransferTx(testWallet, {
await this.signAndSubmitMultiGroupTransferTx(signer, {
signerAddress,
destinations
})

Check failure on line 108 in test/lending.test.ts

View workflow job for this annotation

GitHub Actions / build (20)

Delete `⏎`
}

async transfer(fromUserId: string, toUserData: [string, number][]) {
const fromUserWallet = this.getUserWallet(fromUserId)
const signer = this.getUserWallet(fromUserId)
const signerAddress = signer.address

const destinations = toUserData.map(([user, amount]) => ({
address: this.getUserAddress(user),
attoAlphAmount: convertAlphAmountWithDecimals(amount)!
}))

await this.signAndSubmitMultiGroupTransferTx(fromUserWallet, {
signerAddress: fromUserWallet.address,
destinations: destinations
await this.signAndSubmitMultiGroupTransferTx(signer, {
signerAddress,
destinations
})
}
}
Expand All @@ -134,9 +136,7 @@ async function track<T>(label: string, fn: () => Promise<T>): Promise<T> {

describe('lendingbot', function () {
it('should work', async function () {
const nodeProvider = new NodeProvider('http://127.0.0.1:22973')
const mnemonic = bip39.generateMnemonic()
const lendingBot = new LendingBot(nodeProvider, mnemonic)
const lendingBot = new LendingBot(new NodeProvider('http://127.0.0.1:22973'))

// each user will start with 1 ALPH
const users = ['user0', 'user1', 'user2']
Expand Down
85 changes: 85 additions & 0 deletions test/transaction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { PrivateKeyWallet } from '@alephium/web3-wallet'
import { ONE_ALPH } from '../packages/web3/src'
import { Add, Sub, AddMain } from '../artifacts/ts'
import { getSigner } from '@alephium/web3-test'
import { TransactionBuilder } from '@alephium/web3/dist/src/signer/tx-builder'

describe('transactions', function () {
let signer: PrivateKeyWallet
Expand All @@ -34,6 +35,90 @@ describe('transactions', function () {
signer = await getSigner()
})

it('should build multi-group transfer', async () => {
const nodeProvider = web3.getCurrentNodeProvider()
const signer0 = await getSigner(100n * ONE_ALPH, 0)
const signer1 = await getSigner(0n, 1)
const signer2 = await getSigner(0n, 2)
const signer3 = await getSigner(0n, 3)
const signer4 = await getSigner(0n, 0)

const transferFrom0to1and2 = await TransactionBuilder.from(nodeProvider).buildMultiGroupTransferTx(
{
signerAddress: signer0.address,
destinations: [signer1, signer2].map((signer) => ({
address: signer.address,
attoAlphAmount: 2n * ONE_ALPH
}))
},
signer0.publicKey
)

const transferFrom0to1and2Result = await Promise.all(
transferFrom0to1and2.map(async (tx) => {
return await signer.signAndSubmitUnsignedTx({
signerAddress: signer0.publicKey,
unsignedTx: tx.unsignedTx
})
})
)

const transferFrom1to3and4 = await TransactionBuilder.from(nodeProvider).buildMultiGroupTransferTx(
{
signerAddress: signer1.address,
destinations: [signer3, signer4].map((signer) => ({
address: signer.address,
attoAlphAmount: ONE_ALPH
}))
},
signer1.publicKey
)

const transferFrom1to3and4Result = await Promise.all(
transferFrom1to3and4.map(async (tx) => {
return await signer.signAndSubmitUnsignedTx({
signerAddress: signer1.publicKey,
unsignedTx: tx.unsignedTx
})
})
)

const transferFrom2to3and4 = await TransactionBuilder.from(nodeProvider).buildMultiGroupTransferTx(
{
signerAddress: signer2.address,
destinations: [signer3, signer4].map((signer) => ({
address: signer.address,
attoAlphAmount: ONE_ALPH
}))
},
signer2.publicKey
)

const transferFrom2to3and4Result = await Promise.all(
transferFrom2to3and4.map(async (tx) => {
return await signer.signAndSubmitUnsignedTx({
signerAddress: signer2.publicKey,
unsignedTx: tx.unsignedTx
})
})
)

const signer1Balance = await nodeProvider.addresses.getAddressesAddressBalance(signer0.address)
const signer2Balance = await nodeProvider.addresses.getAddressesAddressBalance(signer1.address)
const signer3Balance = await nodeProvider.addresses.getAddressesAddressBalance(signer2.address)

const gasCostTransferFrom0to1and2 = transferFrom0to1and2Result.reduce((sum, item) => sum + BigInt(item.gasAmount) * BigInt(item.gasPrice), BigInt(0))

Check failure on line 110 in test/transaction.test.ts

View workflow job for this annotation

GitHub Actions / build (20)

Replace `(sum,·item)·=>·sum·+·BigInt(item.gasAmount)·*·BigInt(item.gasPrice),·BigInt(0)` with `⏎······(sum,·item)·=>·sum·+·BigInt(item.gasAmount)·*·BigInt(item.gasPrice),⏎······BigInt(0)⏎····`
const gasCostTransferFrom1to3and4 = transferFrom1to3and4Result.reduce((sum, item) => sum + BigInt(item.gasAmount) * BigInt(item.gasPrice), BigInt(0))

Check failure on line 111 in test/transaction.test.ts

View workflow job for this annotation

GitHub Actions / build (20)

Replace `(sum,·item)·=>·sum·+·BigInt(item.gasAmount)·*·BigInt(item.gasPrice),·BigInt(0)` with `⏎······(sum,·item)·=>·sum·+·BigInt(item.gasAmount)·*·BigInt(item.gasPrice),⏎······BigInt(0)⏎····`
const gasCostTransferFrom2to3and4 = transferFrom2to3and4Result.reduce((sum, item) => sum + BigInt(item.gasAmount) * BigInt(item.gasPrice), BigInt(0))

Check failure on line 112 in test/transaction.test.ts

View workflow job for this annotation

GitHub Actions / build (20)

Replace `(sum,·item)·=>·sum·+·BigInt(item.gasAmount)·*·BigInt(item.gasPrice),·BigInt(0)` with `⏎······(sum,·item)·=>·sum·+·BigInt(item.gasAmount)·*·BigInt(item.gasPrice),⏎······BigInt(0)⏎····`
const expectedSigner1Balance = 100n * ONE_ALPH - 10n * ONE_ALPH - gasCostTransferFrom0to1and2
const expectedSigner2Balance = 10n * ONE_ALPH - 5n * ONE_ALPH - gasCostTransferFrom1to3and4
const expectedSigner3Balance = 5n * ONE_ALPH

expect(BigInt(signer1Balance.balance)).toBe(expectedSigner1Balance)
expect(BigInt(signer2Balance.balance)).toBe(expectedSigner2Balance)
expect(BigInt(signer3Balance.balance)).toBe(expectedSigner3Balance)
})

it('should subscribe transaction status', async () => {
const sub = Sub.contract
const txParams = await sub.txParamsForDeployment(signer, {
Expand Down

0 comments on commit 9feb212

Please sign in to comment.