From 6b9c85954126173c0afef42f3330ba48b8440acd Mon Sep 17 00:00:00 2001 From: josemarinas <36479864+josemarinas@users.noreply.github.com> Date: Thu, 16 Feb 2023 19:07:22 +0100 Subject: [PATCH] Feature: Add voteReplacemeent flag and fix transfers and balances queries (#155) * fix subgraph transfers and balances * add vote replacement flag * update changelog * update dao balances * fix comments * fix tests * fix build * update changelog, examples and docs, fix comments * fix comments * update examples * update examples --- docs/client.md | 10 +- modules/client/CHANGELOG.md | 10 ++ modules/client/examples.md | 20 ++- .../examples/00-client/08-get-balances.ts | 4 +- .../06-multisig-client/03-create-proposal.ts | 2 +- modules/client/package.json | 2 +- .../src/addresslistVoting/interfaces.ts | 2 +- .../internal/client/methods.ts | 12 +- .../internal/graphql-queries/proposal.ts | 5 +- .../src/addresslistVoting/internal/utils.ts | 1 + .../src/client-common/interfaces/common.ts | 6 + .../src/client-common/interfaces/plugin.ts | 1 + modules/client/src/client-common/utils.ts | 14 -- modules/client/src/interfaces.ts | 100 +++++++++------ modules/client/src/internal/client/methods.ts | 86 ++++++++----- .../src/internal/graphql-queries/balances.ts | 23 +++- .../src/internal/graphql-queries/transfer.ts | 45 ++++--- modules/client/src/internal/utils.ts | 120 ++++++++++++------ modules/client/src/tokenVoting/interfaces.ts | 20 ++- .../tokenVoting/internal/client/methods.ts | 26 ++-- .../internal/graphql-queries/proposal.ts | 11 +- .../internal/graphql-queries/token.ts | 5 +- .../client/src/tokenVoting/internal/utils.ts | 17 +-- .../addresslistVoting-client/methods.test.ts | 1 + .../test/integration/client/methods.test.ts | 82 +++++------- modules/client/test/integration/constants.ts | 2 +- .../tokenVoting-client/methods.test.ts | 47 ++++--- modules/common/package.json | 2 +- 28 files changed, 398 insertions(+), 278 deletions(-) diff --git a/docs/client.md b/docs/client.md index a6426e6af..b8685e57c 100644 --- a/docs/client.md +++ b/docs/client.md @@ -235,7 +235,7 @@ This does not estimate the gas cost of updating the allowance of an ERC20 token< * [.hasPermission(params)](#ClientMethods+hasPermission) ⇒ \* * [.getDao(daoAddressOrEns)](#ClientMethods+getDao) ⇒ \* * [.getDaos({)](#ClientMethods+getDaos) ⇒ \* - * [.getDaoBalances(daoAddressorEns)](#ClientMethods+getDaoBalances) ⇒ \* + * [.getDaoBalances({)](#ClientMethods+getDaoBalances) ⇒ \* * [.getDaoTransfers({)](#ClientMethods+getDaoTransfers) ⇒ \* @@ -324,15 +324,15 @@ This does not estimate the gas cost of updating the allowance of an ERC20 token< -### clientMethods.getDaoBalances(daoAddressorEns) ⇒ \* +### clientMethods.getDaoBalances({) ⇒ \*

Retrieves the asset balances of the given DAO, by default, ETH, DAI, USDC and USDT on Mainnet

**Kind**: instance method of [ClientMethods](#ClientMethods) **Returns**: \* -

{(Promise<AssetBalance[] | null>)}

-| Param | Type | -| --- | --- | -| daoAddressorEns | string | +| Param | Type | Description | +| --- | --- | --- | +| { | DaoBalancesQueryParams |

daoAddressOrEns, limit = 10, skip = 0, direction = SortDirection.ASC, sortBy = AssetBalanceSortBy.LAST_UPDATED, }

| diff --git a/modules/client/CHANGELOG.md b/modules/client/CHANGELOG.md index 946b77ce3..8e09d327b 100644 --- a/modules/client/CHANGELOG.md +++ b/modules/client/CHANGELOG.md @@ -13,6 +13,13 @@ TEMPLATE: --> +## [0.20.0-beta] +### Changed +- Update `getDaoBalances` parameters from `daoAddressOrEns` to `DaoBalancesQueryParams` + +### Added +- Add support for Subgraph version `0.7.2-alpha` +- Add Vote Replacement flag in MajorityVoting clients ## [0.20.0-beta] ### Changed - Updates to contracts-ethers v0.7.1 @@ -50,6 +57,9 @@ TEMPLATE: ## [0.19.0-alpha] +### Fixed +- Transfer and Balances queries + ## [0.18.0-alpha] ### Added - Add `pinMetadata` examples diff --git a/modules/client/examples.md b/modules/client/examples.md index be87488a9..cdff0ffe8 100644 --- a/modules/client/examples.md +++ b/modules/client/examples.md @@ -425,7 +425,9 @@ import { contextParams } from "./00-context"; const context: Context = new Context(contextParams); const client: Client = new Client(context); const daoAddressOrEns = "0x12345..."; -const balances: AssetBalance[] | null = await client.methods.getDaoBalances(daoAddressOrEns); +const balances: AssetBalance[] | null = await client.methods.getDaoBalances({ + daoAddressOrEns: daoAddressOrEns, +}); console.log(balances); /* [ @@ -2365,14 +2367,22 @@ import { Client, Context, WithdrawParams } from "@aragon/sdk-client"; import { contextParams } from "../00-client/00-context"; const context: Context = new Context(contextParams); const client: Client = new Client(context); -const data: Uint8Array = new Uint8Array([12, 56]); -const params: WithdrawParams = client.decoding.withdrawAction(data); +const action = { + to: "0x", + value: BigInt(0), + data: new Uint8Array([12, 56]), +}; +const params: WithdrawParams = client.decoding.withdrawAction( + action.to, + action.value, + action.data, +); console.log(params); /* { - type: "Erc20", + type: "erc20", recipientAddress: "0x1234567890123456789012345678901234567890", amount: 10n, tokenAddress: "0x1234567890123456789012345678901234567890", @@ -2875,7 +2885,7 @@ import { TokenType, WithdrawParams, } from "@aragon/sdk-client"; -import {} from "../../src/interfaces"; + import { contextParams } from "../00-client/00-context"; // Create a simple context diff --git a/modules/client/examples/00-client/08-get-balances.ts b/modules/client/examples/00-client/08-get-balances.ts index 088d45c22..54d0a979d 100644 --- a/modules/client/examples/00-client/08-get-balances.ts +++ b/modules/client/examples/00-client/08-get-balances.ts @@ -9,7 +9,9 @@ import { contextParams } from "./00-context"; const context: Context = new Context(contextParams); const client: Client = new Client(context); const daoAddressOrEns = "0x12345..."; -const balances: AssetBalance[] | null = await client.methods.getDaoBalances(daoAddressOrEns); +const balances: AssetBalance[] | null = await client.methods.getDaoBalances({ + daoAddressOrEns: daoAddressOrEns, +}); console.log(balances); /* [ diff --git a/modules/client/examples/06-multisig-client/03-create-proposal.ts b/modules/client/examples/06-multisig-client/03-create-proposal.ts index 9c3db5213..414ebff66 100644 --- a/modules/client/examples/06-multisig-client/03-create-proposal.ts +++ b/modules/client/examples/06-multisig-client/03-create-proposal.ts @@ -12,7 +12,7 @@ import { TokenType, WithdrawParams, } from "@aragon/sdk-client"; -import {} from "../../src/interfaces"; + import { contextParams } from "../00-client/00-context"; // Create a simple context diff --git a/modules/client/package.json b/modules/client/package.json index aa0f8b5c2..5d8185a81 100644 --- a/modules/client/package.json +++ b/modules/client/package.json @@ -1,7 +1,7 @@ { "name": "@aragon/sdk-client", "author": "Aragon Association", - "version": "0.20.0-beta", + "version": "0.21.0-beta", "license": "MIT", "main": "dist/index.js", "module": "dist/sdk-client.esm.js", diff --git a/modules/client/src/addresslistVoting/interfaces.ts b/modules/client/src/addresslistVoting/interfaces.ts index 338c86ecc..d8f8cc6d7 100644 --- a/modules/client/src/addresslistVoting/interfaces.ts +++ b/modules/client/src/addresslistVoting/interfaces.ts @@ -91,7 +91,7 @@ export interface IAddresslistVotingClient { export type AddresslistVotingProposal = ProposalBase & { result: AddresslistVotingProposalResult; settings: IProposalSettings; - votes: Array<{ address: string; vote: VoteValues }>; + votes: Array<{ address: string; vote: VoteValues, voteReplaced: boolean }>; totalVotingWeight: number; creationBlockNumber: number; executionDate: Date; diff --git a/modules/client/src/addresslistVoting/internal/client/methods.ts b/modules/client/src/addresslistVoting/internal/client/methods.ts index 93a9115c7..d5856bd56 100644 --- a/modules/client/src/addresslistVoting/internal/client/methods.ts +++ b/modules/client/src/addresslistVoting/internal/client/methods.ts @@ -1,5 +1,6 @@ import { boolArrayToBitmap, + decodeRatio, GraphQLError, InvalidAddressError, InvalidAddressOrEnsError, @@ -32,7 +33,6 @@ import { IExecuteProposalParams, IProposalQueryParams, IVoteProposalParams, - parseEtherRatio, ProposalCreationSteps, ProposalCreationStepValue, ProposalMetadata, @@ -481,11 +481,13 @@ export class AddresslistVotingClientMethods extends ClientCore } return { minDuration: parseInt(addresslistVotingPlugin.minDuration), - supportThreshold: parseEtherRatio( - addresslistVotingPlugin.supportThreshold, + supportThreshold: decodeRatio( + BigInt(addresslistVotingPlugin.supportThreshold), + 6, ), - minParticipation: parseEtherRatio( - addresslistVotingPlugin.minParticipation, + minParticipation: decodeRatio( + BigInt(addresslistVotingPlugin.minParticipation), + 6, ), minProposerVotingPower: BigInt( addresslistVotingPlugin.minProposerVotingPower, diff --git a/modules/client/src/addresslistVoting/internal/graphql-queries/proposal.ts b/modules/client/src/addresslistVoting/internal/graphql-queries/proposal.ts index 1219dc9c7..b25c943f0 100644 --- a/modules/client/src/addresslistVoting/internal/graphql-queries/proposal.ts +++ b/modules/client/src/addresslistVoting/internal/graphql-queries/proposal.ts @@ -19,8 +19,8 @@ query AddresslistVotingProposal($proposalId: ID!) { value data } - yes, - no, + yes + no abstain votingMode supportThreshold @@ -33,6 +33,7 @@ query AddresslistVotingProposal($proposalId: ID!) { address } voteOption + voteReplaced } totalVotingPower minVotingPower diff --git a/modules/client/src/addresslistVoting/internal/utils.ts b/modules/client/src/addresslistVoting/internal/utils.ts index cd270bdfc..797f10b61 100644 --- a/modules/client/src/addresslistVoting/internal/utils.ts +++ b/modules/client/src/addresslistVoting/internal/utils.ts @@ -83,6 +83,7 @@ export function toAddresslistVotingProposal( votes: proposal.voters.map( (voter: SubgraphAddresslistVotingVoterListItem) => { return { + voteReplaced: voter.voteReplaced, address: voter.voter.address, vote: SubgraphVoteValuesMap.get(voter.voteOption) as VoteValues, }; diff --git a/modules/client/src/client-common/interfaces/common.ts b/modules/client/src/client-common/interfaces/common.ts index 9078f6b33..5e91942b2 100644 --- a/modules/client/src/client-common/interfaces/common.ts +++ b/modules/client/src/client-common/interfaces/common.ts @@ -45,6 +45,12 @@ export interface IPagination { direction?: SortDirection; } +export type Pagination = { + skip?: number; + limit?: number; + direction?: SortDirection; +}; + export enum SortDirection { ASC = "asc", DESC = "desc", diff --git a/modules/client/src/client-common/interfaces/plugin.ts b/modules/client/src/client-common/interfaces/plugin.ts index 2379d0d03..92c006239 100644 --- a/modules/client/src/client-common/interfaces/plugin.ts +++ b/modules/client/src/client-common/interfaces/plugin.ts @@ -173,6 +173,7 @@ export type SubgraphVoterListItemBase = { voter: { address: string; }; + voteReplaced: boolean voteOption: SubgraphVoteValues; }; diff --git a/modules/client/src/client-common/utils.ts b/modules/client/src/client-common/utils.ts index c32b45c0e..84dff4a66 100644 --- a/modules/client/src/client-common/utils.ts +++ b/modules/client/src/client-common/utils.ts @@ -11,8 +11,6 @@ import { Interface } from "@ethersproject/abi"; import { id } from "@ethersproject/hash"; import { Log } from "@ethersproject/providers"; import { InvalidVotingModeError } from "@aragon/sdk-common"; -import { formatEther } from "@ethersproject/units"; -import { InvalidPrecisionError } from "@aragon/sdk-common"; export function unwrapProposalParams( params: ICreateProposalParams, @@ -125,15 +123,3 @@ export function votingModeFromContracts(votingMode: number): VotingMode { } } -// TODO -// delete me -export function parseEtherRatio(ether: string, precision: number = 2): number { - if (precision <= 0 || !Number.isInteger(precision)) { - throw new InvalidPrecisionError(); - } - return parseFloat( - parseFloat( - formatEther(ether), - ).toFixed(precision), - ); -} diff --git a/modules/client/src/interfaces.ts b/modules/client/src/interfaces.ts index 482a4dbb4..4d74a0fde 100644 --- a/modules/client/src/interfaces.ts +++ b/modules/client/src/interfaces.ts @@ -6,6 +6,7 @@ import { IInterfaceParams, IPagination, IPluginInstallItem, + Pagination, } from "./client-common/interfaces/common"; import { keccak256 } from "@ethersproject/keccak256"; import { toUtf8Bytes } from "@ethersproject/strings"; @@ -18,7 +19,7 @@ export interface IClientMethods extends IClientCore { pinMetadata: (params: DaoMetadata) => Promise; /** Retrieves the asset balances of the given DAO, by default, ETH, DAI, USDC and USDT on Mainnet*/ getDaoBalances: ( - daoAddressOrEns: string, + params: DaoBalancesQueryParams, ) => Promise; /** Retrieves the list of transfers from or to the given DAO, by default, ETH, DAI, USDC and USDT on Mainnet*/ getDaoTransfers: (params: ITransferQueryParams) => Promise; @@ -177,7 +178,7 @@ export enum DaoCreationSteps { export type DaoCreationStepValue = | { key: DaoCreationSteps.CREATING; txHash: string } - | { key: DaoCreationSteps.DONE; address: string, pluginAddresses: string[] }; + | { key: DaoCreationSteps.DONE; address: string; pluginAddresses: string[] }; // DEPOSIT @@ -224,33 +225,34 @@ export type DaoDepositStepValue = | { key: DaoDepositSteps.DEPOSITING; txHash: string } | { key: DaoDepositSteps.DONE; amount: bigint }; -// Token types +// Token balances -type NativeTokenBase = { - type: "native"; -}; -type Erc20TokenBase = { - type: "erc20"; - /** The address of the token contract */ +type AssetBalanceBase = { address: string; name: string; symbol: string; - decimals: number; + updateDate: Date; }; -// Token balances - -type NativeTokenBalance = NativeTokenBase & { +type NativeAssetBalance = { + type: TokenType.NATIVE; balance: bigint; + updateDate: Date; }; -type Erc20TokenBalance = Erc20TokenBase & { +type Erc20AssetBalance = AssetBalanceBase & { + type: TokenType.ERC20; balance: bigint; + decimals: number; }; - -export type AssetBalance = (NativeTokenBalance | Erc20TokenBalance) & { - updateDate: Date; +type Erc721AssetBalance = AssetBalanceBase & { + type: TokenType.ERC721; }; +export type AssetBalance = + | NativeAssetBalance + | Erc20AssetBalance + | Erc721AssetBalance; + // Token transfers export enum TransferType { DEPOSIT = "deposit", @@ -259,20 +261,33 @@ export enum TransferType { export enum TokenType { NATIVE = "native", ERC20 = "erc20", + ERC721 = "erc721", } type BaseTokenTransfer = { - amount: bigint; creationDate: Date; transactionId: string; + to: string; + from: string; }; type NativeTokenTransfer = BaseTokenTransfer & { tokenType: TokenType.NATIVE; + amount: bigint; +}; + +type Erc721TokenTransfer = BaseTokenTransfer & { + tokenType: TokenType.ERC721; + token: { + address: string; + name: string; + symbol: string; + }; }; type Erc20TokenTransfer = BaseTokenTransfer & { tokenType: TokenType.ERC20; + amount: bigint; token: { address: string; name: string; @@ -281,16 +296,18 @@ type Erc20TokenTransfer = BaseTokenTransfer & { }; }; -export type Deposit = (NativeTokenTransfer | Erc20TokenTransfer) & { - from: string; - type: TransferType.DEPOSIT; -}; +export type Deposit = + & (NativeTokenTransfer | Erc20TokenTransfer | Erc721TokenTransfer) + & { + type: TransferType.DEPOSIT; + }; -export type Withdraw = (NativeTokenTransfer | Erc20TokenTransfer) & { - to: string; - type: TransferType.WITHDRAW; - proposalId: string; -}; +export type Withdraw = + & (NativeTokenTransfer | Erc20TokenTransfer | Erc721TokenTransfer) + & { + type: TransferType.WITHDRAW; + proposalId: string; + }; export type Transfer = Deposit | Withdraw; @@ -330,9 +347,16 @@ export interface ITransferQueryParams extends IPagination { type?: TransferType; daoAddressOrEns?: string; } - export enum TransferSortBy { - CREATED_AT = "createdAt", // currently defined as number of proposals + CREATED_AT = "createdAt", +} + +export type DaoBalancesQueryParams = Pagination & { + sortBy?: AssetBalanceSortBy; + daoAddressOrEns?: string; +}; +export enum AssetBalanceSortBy { + LAST_UPDATED = "lastUpdated", } export enum DaoSortBy { @@ -377,11 +401,12 @@ export type SubgraphDao = SubgraphDaoBase & { export type SubgraphDaoListItem = SubgraphDaoBase; export type SubgraphBalance = { + __typename: string; token: { id: string; name: string; symbol: string; - decimals: string; + decimals: number; }; balance: string; lastUpdated: string; @@ -393,23 +418,24 @@ export enum SubgraphTransferType { } export type SubgraphTransferListItem = { - amount: string; - createdAt: string; - transaction: string; - type: SubgraphTransferType; + from: string; to: string; - sender: string; - token: SubgraphToken; + type: SubgraphTransferType; + createdAt: string; + txHash: string; proposal: { id: string | null; }; + amount: string; + token: SubgraphToken; + __typename: string; }; export type SubgraphToken = { id: string; name: string; symbol: string; - decimals: string; + decimals: number; }; export const SubgraphTransferTypeMap: Map< TransferType, diff --git a/modules/client/src/internal/client/methods.ts b/modules/client/src/internal/client/methods.ts index 88ca98df6..5b812d6cc 100644 --- a/modules/client/src/internal/client/methods.ts +++ b/modules/client/src/internal/client/methods.ts @@ -22,13 +22,15 @@ import { Contract, ContractTransaction } from "@ethersproject/contracts"; import { erc20ContractAbi } from "../abi/erc20"; import { QueryDao, - QueryDaoBalances, QueryDaos, - QueryDaoTransfers, + QueryTokenBalances, + QueryTokenTransfers, } from "../graphql-queries"; import { AssetBalance, + AssetBalanceSortBy, CreateDaoParams, + DaoBalancesQueryParams, DaoCreationSteps, DaoCreationStepValue, DaoDepositSteps, @@ -64,7 +66,7 @@ import { toAssetBalance, toDaoDetails, toDaoListItem, - toTransfer, + toTokenTransfer, unwrapDepositParams, } from "../utils"; import { isAddress } from "@ethersproject/address"; @@ -488,48 +490,64 @@ export class ClientMethods extends ClientCore implements IClientMethods { } catch (err) { throw new GraphQLError("DAO"); } - } + } /** * Retrieves the asset balances of the given DAO, by default, ETH, DAI, USDC and USDT on Mainnet * - * @param {string} daoAddressorEns + * @param {DaoBalancesQueryParams} { + * daoAddressOrEns, + * limit = 10, + * skip = 0, + * direction = SortDirection.ASC, + * sortBy = AssetBalanceSortBy.LAST_UPDATED, + * } * @return {*} {(Promise)} * @memberof ClientMethods */ - public async getDaoBalances( - daoAddressorEns: string, - ): Promise { - let address = daoAddressorEns; - if (!isAddress(address)) { - await this.web3.ensureOnline(); - const provider = this.web3.getProvider(); - if (!provider) { - throw new NoProviderError(); - } - const resolvedAddress = await provider.resolveName(address); - if (!resolvedAddress) { - throw new InvalidAddressOrEnsError(); + public async getDaoBalances({ + daoAddressOrEns, + limit = 10, + skip = 0, + direction = SortDirection.ASC, + sortBy = AssetBalanceSortBy.LAST_UPDATED, + }: DaoBalancesQueryParams): Promise { + let where = {}; + let address = daoAddressOrEns; + if (address) { + if (!isAddress(address)) { + await this.web3.ensureOnline(); + const provider = this.web3.getProvider(); + if (!provider) { + throw new NoProviderError(); + } + const resolvedAddress = await provider.resolveName(address); + if (!resolvedAddress) { + throw new InvalidAddressOrEnsError(); + } + address = resolvedAddress; } - address = resolvedAddress; + where = { dao: address }; } try { await this.graphql.ensureOnline(); const client = this.graphql.getClient(); const { - balances, - }: { balances: SubgraphBalance[] } = await client.request( - QueryDaoBalances, + tokenBalances, + }: { tokenBalances: SubgraphBalance[] } = await client.request( + QueryTokenBalances, { - address, + where, + limit, + skip, + direction, + sortBy, }, ); - if (balances.length === 0) { + if (tokenBalances.length === 0) { return []; } - // TODO - // handle other tokens that are not ERC20 or eth return Promise.all( - balances.map( + tokenBalances.map( (balance: SubgraphBalance): AssetBalance => toAssetBalance(balance), ), ); @@ -583,9 +601,9 @@ export class ClientMethods extends ClientCore implements IClientMethods { await this.graphql.ensureOnline(); const client = this.graphql.getClient(); const { - vaultTransfers, - }: { vaultTransfers: SubgraphTransferListItem[] } = await client.request( - QueryDaoTransfers, + tokenTransfers, + }: { tokenTransfers: SubgraphTransferListItem[] } = await client.request( + QueryTokenTransfers, { where, limit, @@ -594,17 +612,17 @@ export class ClientMethods extends ClientCore implements IClientMethods { sortBy, }, ); - if (!vaultTransfers) { + if (!tokenTransfers) { return null; } return Promise.all( - vaultTransfers.map( + tokenTransfers.map( (transfer: SubgraphTransferListItem): Transfer => - toTransfer(transfer), + toTokenTransfer(transfer), ), ); } catch { - throw new GraphQLError("transfer"); + throw new GraphQLError("token transfer"); } } } diff --git a/modules/client/src/internal/graphql-queries/balances.ts b/modules/client/src/internal/graphql-queries/balances.ts index fff7adc32..d750dc13f 100644 --- a/modules/client/src/internal/graphql-queries/balances.ts +++ b/modules/client/src/internal/graphql-queries/balances.ts @@ -1,16 +1,29 @@ import { gql } from "graphql-request"; -export const QueryDaoBalances = gql` -query DaoBalances($address: ID!, $limit: Int = 10, $skip: Int = 0) { - balances(where:{dao:$address}) { +export const QueryTokenBalances = gql` +query TokenBalances($where: TokenBalance_filter!, $limit:Int!, $skip: Int!, $direction: OrderDirection!, $sortBy: TokenBalance_orderBy!) { + tokenBalances (where: $where, first: $limit, skip: $skip, orderDirection: $direction, orderBy: $sortBy) { + lastUpdated + __typename + ... on ERC20Balance { + balance token { + name + decimals + symbol id + } + } + ... on ERC721Balance { + token { name symbol - decimals + id } + } + ... on NativeBalance { balance - lastUpdated } } +} `; diff --git a/modules/client/src/internal/graphql-queries/transfer.ts b/modules/client/src/internal/graphql-queries/transfer.ts index 92a1ec971..c67c4fa95 100644 --- a/modules/client/src/internal/graphql-queries/transfer.ts +++ b/modules/client/src/internal/graphql-queries/transfer.ts @@ -1,24 +1,37 @@ import { gql } from "graphql-request"; -export const QueryDaoTransfers = gql` -query DaoTransfers($where: VaultTransfer_filter!, $limit:Int!, $skip: Int!, $direction: OrderDirection!, $sortBy: VaultTransfer_orderBy!) { - vaultTransfers(where: $where, first: $limit, skip: $skip, orderDirection: $direction, orderBy: $sortBy){ - token { - id - name - symbol - decimals - } +export const QueryTokenTransfers = gql` +query TokenTransfers($where: TokenTransfer_filter!, $limit:Int!, $skip: Int!, $direction: OrderDirection!, $sortBy: TokenTransfer_orderBy!) { + tokenTransfers (where: $where, first: $limit, skip: $skip, orderDirection: $direction, orderBy: $sortBy) { + from + to + type + createdAt + txHash proposal{ id } - type - amount - createdAt - transaction - sender - to - reference + __typename + ... on ERC20Transfer { + amount + token { + id + name + symbol + decimals + } + } + ... on ERC721Transfer { + token{ + id + name + symbol + } + + } + ... on NativeTransfer { + amount + } } } `; diff --git a/modules/client/src/internal/utils.ts b/modules/client/src/internal/utils.ts index 5265e3670..97ad50333 100644 --- a/modules/client/src/internal/utils.ts +++ b/modules/client/src/internal/utils.ts @@ -1,5 +1,4 @@ import { - AssetBalance, ContractPermissionParams, DaoDetails, DaoListItem, @@ -19,6 +18,7 @@ import { SubgraphPluginTypeMap, SubgraphTransferListItem, SubgraphTransferType, + AssetBalance, TokenType, Transfer, TransferType, @@ -110,35 +110,45 @@ export function toDaoListItem( export function toAssetBalance(balance: SubgraphBalance): AssetBalance { const updateDate = new Date(parseInt(balance.lastUpdated) * 1000); - if (balance.token.symbol === "ETH") { + if (balance.__typename === "NativeBalance") { return { - type: "native", + type: TokenType.NATIVE, + balance: BigInt(balance.balance), + updateDate, + }; + } else if (balance.__typename === "ERC721Balance") { + return { + type: TokenType.ERC721, + name: balance.token.symbol, + symbol: balance.token.symbol, + updateDate, + address: balance.token.id, + }; + } else { + return { + type: TokenType.ERC20, + address: balance.token.id, + name: balance.token.name, + symbol: balance.token.symbol, + decimals: balance.token.decimals, balance: BigInt(balance.balance), updateDate, }; } - return { - type: "erc20", - address: balance.token.id, - name: balance.token.name, - symbol: balance.token.symbol, - decimals: parseInt(balance.token.decimals), - balance: BigInt(balance.balance), - updateDate, - }; } -export function toTransfer(transfer: SubgraphTransferListItem): Transfer { +export function toTokenTransfer(transfer: SubgraphTransferListItem): Transfer { const creationDate = new Date(parseInt(transfer.createdAt) * 1000); - if (transfer.token.symbol === "ETH") { + if (transfer.__typename === "NativeTransfer") { if (transfer.type === SubgraphTransferType.DEPOSIT) { return { type: TransferType.DEPOSIT, tokenType: TokenType.NATIVE, amount: BigInt(transfer.amount), creationDate, - transactionId: transfer.transaction, - from: transfer.sender, + transactionId: transfer.txHash, + from: transfer.from, + to: transfer.to, }; } return { @@ -146,42 +156,76 @@ export function toTransfer(transfer: SubgraphTransferListItem): Transfer { tokenType: TokenType.NATIVE, amount: BigInt(transfer.amount), creationDate, - transactionId: transfer.transaction, + transactionId: transfer.txHash, proposalId: transfer.proposal?.id || "", to: transfer.to, + from: transfer.from, }; - } - if (transfer.type === SubgraphTransferType.DEPOSIT) { + } else if (transfer.__typename === "ERC721Transfer") { + if (transfer.type === SubgraphTransferType.DEPOSIT) { + return { + type: TransferType.DEPOSIT, + tokenType: TokenType.ERC721, + token: { + address: transfer.token.id, + name: transfer.token.name, + symbol: transfer.token.symbol, + }, + creationDate, + transactionId: transfer.txHash, + from: transfer.from, + to: transfer.to, + }; + } return { - type: TransferType.DEPOSIT, + type: TransferType.WITHDRAW, + tokenType: TokenType.ERC721, + token: { + address: transfer.token.id, + name: transfer.token.name, + symbol: transfer.token.symbol, + }, + creationDate, + transactionId: transfer.txHash, + to: transfer.to, + from: transfer.from, + proposalId: transfer.proposal.id || "", + }; + } else { + if (transfer.type === SubgraphTransferType.DEPOSIT) { + return { + type: TransferType.DEPOSIT, + tokenType: TokenType.ERC20, + token: { + address: transfer.token.id, + name: transfer.token.name, + symbol: transfer.token.symbol, + decimals: transfer.token.decimals, + }, + amount: BigInt(transfer.amount), + creationDate, + transactionId: transfer.txHash, + from: transfer.from, + to: transfer.to, + }; + } + return { + type: TransferType.WITHDRAW, tokenType: TokenType.ERC20, token: { address: transfer.token.id, name: transfer.token.name, symbol: transfer.token.symbol, - decimals: parseInt(transfer.token.decimals), + decimals: transfer.token.decimals, }, amount: BigInt(transfer.amount), creationDate, - transactionId: transfer.transaction, - from: transfer.sender, + transactionId: transfer.txHash, + to: transfer.to, + from: transfer.from, + proposalId: transfer.proposal.id || "", }; } - return { - type: TransferType.WITHDRAW, - tokenType: TokenType.ERC20, - token: { - address: transfer.token.id, - name: transfer.token.name, - symbol: transfer.token.symbol, - decimals: parseInt(transfer.token.decimals), - }, - amount: BigInt(transfer.amount), - creationDate, - transactionId: transfer.transaction, - to: transfer.to, - proposalId: transfer.proposal.id || "", - }; } export function permissionParamsToContract( diff --git a/modules/client/src/tokenVoting/interfaces.ts b/modules/client/src/tokenVoting/interfaces.ts index 4734d51ad..223516a5b 100644 --- a/modules/client/src/tokenVoting/interfaces.ts +++ b/modules/client/src/tokenVoting/interfaces.ts @@ -26,6 +26,7 @@ import { VotingMode, VotingSettings, } from "../client-common"; +import { TokenType } from "../interfaces"; // TokenVoting @@ -111,7 +112,9 @@ export type TokenVotingProposal = ProposalBase & { settings: IProposalSettings; token: Erc20TokenDetails | Erc721TokenDetails | null; usedVotingWeight: bigint; - votes: Array<{ address: string; vote: VoteValues; weight: bigint }>; + votes: Array< + { address: string; vote: VoteValues; weight: bigint; voteReplaced: boolean } + >; totalVotingWeight: bigint; creationBlockNumber: number; executionDate: Date; @@ -132,9 +135,10 @@ export type TokenVotingProposalResult = { export type Erc20TokenDetails = TokenBaseDetails & { decimals: number; + type: TokenType.ERC20; }; export type Erc721TokenDetails = TokenBaseDetails & { - baseUri: string; + type: TokenType.ERC721; }; export type TokenBaseDetails = { @@ -157,19 +161,23 @@ type SubgraphBaseToken = { symbol: string; name: string; id: string; - __typename: SubgraphTokenType; }; export enum SubgraphTokenType { ERC20 = "ERC20Token", ERC721 = "ERC721Token", } +export enum SubgraphContractType { + ERC20 = "ERC20Contract", + ERC721 = "ERC721Contract", +} export type SubgraphErc20Token = SubgraphBaseToken & { - decimals: string; + __typename: SubgraphContractType.ERC20; + decimals: number; }; export type SubgraphErc721Token = SubgraphBaseToken & { - baseURI: string; -}; + __typename: SubgraphContractType.ERC721; +} export type SubgraphTokenVotingProposal = & SubgraphTokenVotingProposalListItem diff --git a/modules/client/src/tokenVoting/internal/client/methods.ts b/modules/client/src/tokenVoting/internal/client/methods.ts index f998208d0..cf2237e9d 100644 --- a/modules/client/src/tokenVoting/internal/client/methods.ts +++ b/modules/client/src/tokenVoting/internal/client/methods.ts @@ -1,6 +1,7 @@ import { isAddress } from "@ethersproject/address"; import { boolArrayToBitmap, + decodeRatio, GraphQLError, InvalidAddressError, InvalidAddressOrEnsError, @@ -26,7 +27,6 @@ import { IProposalQueryParams, isProposalId, IVoteProposalParams, - parseEtherRatio, ProposalCreationSteps, ProposalCreationStepValue, ProposalMetadata, @@ -41,9 +41,9 @@ import { Erc20TokenDetails, Erc721TokenDetails, ITokenVotingClientMethods, + SubgraphContractType, SubgraphErc20Token, SubgraphErc721Token, - SubgraphTokenType, SubgraphTokenVotingProposal, SubgraphTokenVotingProposalListItem, TokenVotingProposal, @@ -64,6 +64,7 @@ import { UNSUPPORTED_PROPOSAL_METADATA_LINK, } from "../../../client-common/constants"; import { BigNumber } from "@ethersproject/bignumber"; +import { TokenType } from "../../../interfaces"; /** * Methods module the SDK TokenVoting Client @@ -473,11 +474,13 @@ export class TokenVotingClientMethods extends ClientCore } return { minDuration: parseInt(tokenVotingPlugin.minDuration), - supportThreshold: parseEtherRatio( - tokenVotingPlugin.supportThreshold, + supportThreshold: decodeRatio( + BigInt(tokenVotingPlugin.supportThreshold), + 6, ), - minParticipation: parseEtherRatio( - tokenVotingPlugin.minParticipation, + minParticipation: decodeRatio( + BigInt(tokenVotingPlugin.minParticipation), + 6, ), minProposerVotingPower: BigInt( tokenVotingPlugin.minProposerVotingPower, @@ -517,22 +520,21 @@ export class TokenVotingClientMethods extends ClientCore let token: SubgraphErc20Token | SubgraphErc721Token = tokenVotingPlugin.token; // type erc20 - if (token.__typename === SubgraphTokenType.ERC20) { - token = token as SubgraphErc20Token; + if (token.__typename === SubgraphContractType.ERC20) { return { address: token.id, name: token.name, symbol: token.symbol, - decimals: parseInt(token.decimals), + decimals: token.decimals, + type: TokenType.ERC20, }; // type erc721 - } else if (token.__typename === SubgraphTokenType.ERC721) { - token = token as SubgraphErc721Token; + } else if (token.__typename === SubgraphContractType.ERC721) { return { address: token.id, name: token.name, symbol: token.symbol, - baseUri: token.baseURI, + type: TokenType.ERC721, }; } return null; diff --git a/modules/client/src/tokenVoting/internal/graphql-queries/proposal.ts b/modules/client/src/tokenVoting/internal/graphql-queries/proposal.ts index 77970a1c6..e79e0587e 100644 --- a/modules/client/src/tokenVoting/internal/graphql-queries/proposal.ts +++ b/modules/client/src/tokenVoting/internal/graphql-queries/proposal.ts @@ -32,6 +32,7 @@ query TokenVotingProposal($proposalId: ID!) { voter{ address } + voteReplaced voteOption votingPower } @@ -41,12 +42,9 @@ query TokenVotingProposal($proposalId: ID!) { name symbol __typename - ...on ERC20Token { + ...on ERC20Contract { decimals } - ...on ERC721Token { - baseURI - } } } totalVotingPower @@ -77,12 +75,9 @@ query TokenVotingProposals($where: TokenVotingProposal_filter!, $limit:Int!, $sk name symbol __typename - ...on ERC20Token { + ...on ERC20Contract { decimals } - ...on ERC721Token { - baseURI - } } } } diff --git a/modules/client/src/tokenVoting/internal/graphql-queries/token.ts b/modules/client/src/tokenVoting/internal/graphql-queries/token.ts index ab617dee5..5a0637e19 100644 --- a/modules/client/src/tokenVoting/internal/graphql-queries/token.ts +++ b/modules/client/src/tokenVoting/internal/graphql-queries/token.ts @@ -8,12 +8,9 @@ query TokenVotingPlugin($address: ID!) { name symbol __typename - ...on ERC20Token { + ...on ERC20Contract { decimals } - ...on ERC721Token { - baseURI - } } } } diff --git a/modules/client/src/tokenVoting/internal/utils.ts b/modules/client/src/tokenVoting/internal/utils.ts index 4ec3b904f..fc49d2147 100644 --- a/modules/client/src/tokenVoting/internal/utils.ts +++ b/modules/client/src/tokenVoting/internal/utils.ts @@ -15,9 +15,9 @@ import { Erc721TokenDetails, IMintTokenParams, ITokenVotingPluginInstall, + SubgraphContractType, SubgraphErc20Token, SubgraphErc721Token, - SubgraphTokenType, SubgraphTokenVotingProposal, SubgraphTokenVotingProposalListItem, SubgraphTokenVotingVoterListItem, @@ -28,6 +28,7 @@ import { BigNumber } from "@ethersproject/bignumber"; import { Result } from "@ethersproject/abi"; import { AddressZero } from "@ethersproject/constants"; import { decodeRatio, hexToBytes } from "@aragon/sdk-common"; +import { TokenType } from "../../interfaces"; export function toTokenVotingProposal( proposal: SubgraphTokenVotingProposal, @@ -100,6 +101,7 @@ export function toTokenVotingProposal( votes: proposal.voters.map( (voter: SubgraphTokenVotingVoterListItem) => { return { + voteReplaced: voter.voteReplaced, address: voter.voter.address, vote: SubgraphVoteValuesMap.get(voter.voteOption) as VoteValues, weight: BigInt(voter.votingPower), @@ -180,22 +182,21 @@ export function tokenVotingInitParamsToContract( function parseToken( subgraphToken: SubgraphErc20Token | SubgraphErc721Token, ): Erc20TokenDetails | Erc721TokenDetails | null { - let token = null; - if (subgraphToken.__typename === SubgraphTokenType.ERC20) { - subgraphToken = subgraphToken as SubgraphErc20Token; + let token: Erc721TokenDetails| Erc20TokenDetails | null = null; + if (subgraphToken.__typename === SubgraphContractType.ERC20) { token = { address: subgraphToken.id, symbol: subgraphToken.symbol, name: subgraphToken.name, - decimals: parseInt(subgraphToken.decimals), + decimals: subgraphToken.decimals, + type: TokenType.ERC20 }; - } else if (subgraphToken.__typename === SubgraphTokenType.ERC721) { - subgraphToken = subgraphToken as SubgraphErc721Token; + } else if (subgraphToken.__typename === SubgraphContractType.ERC721) { token = { address: subgraphToken.id, symbol: subgraphToken.symbol, name: subgraphToken.name, - baseUri: subgraphToken.baseURI, + type: TokenType.ERC721 }; } return token; diff --git a/modules/client/test/integration/addresslistVoting-client/methods.test.ts b/modules/client/test/integration/addresslistVoting-client/methods.test.ts index 3dc5ec98a..bd3392e32 100644 --- a/modules/client/test/integration/addresslistVoting-client/methods.test.ts +++ b/modules/client/test/integration/addresslistVoting-client/methods.test.ts @@ -634,6 +634,7 @@ describe("Client Address List", () => { expect(typeof vote.address).toBe("string"); expect(vote.address).toMatch(/^0x[A-Fa-f0-9]{40}$/i); expect(typeof vote.vote).toBe("number"); + expect(typeof vote.voteReplaced).toBe("boolean"); } if (proposal.executionTxHash) { expect(proposal.executionTxHash).toMatch(/^0x[A-Fa-f0-9]{64}$/i); diff --git a/modules/client/test/integration/client/methods.test.ts b/modules/client/test/integration/client/methods.test.ts index 77cef9c15..c4fe599ee 100644 --- a/modules/client/test/integration/client/methods.test.ts +++ b/modules/client/test/integration/client/methods.test.ts @@ -7,12 +7,12 @@ import { mockedIPFSClient } from "../../mocks/aragon-sdk-ipfs"; import * as ganacheSetup from "../../helpers/ganache-setup"; import * as deployContracts from "../../helpers/deployContracts"; import { - contextParamsMainnet, contextParamsLocalChain, TEST_DAO_ADDRESS, TEST_INVALID_ADDRESS, TEST_NO_BALANCES_DAO_ADDRESS, TEST_NON_EXISTING_ADDRESS, + contextParamsMainnet, // TEST_WALLET, } from "../constants"; import { @@ -37,7 +37,6 @@ import { VotingMode, } from "../../../src"; import { - InvalidAddressOrEnsError, MissingExecPermissionError, Random, } from "@aragon/sdk-common"; @@ -413,13 +412,11 @@ describe("Client", () => { const ctx = new Context(contextParamsMainnet); const client = new Client(ctx); const daoAddress = TEST_INVALID_ADDRESS; - await expect(() => client.methods.getDao(daoAddress)).rejects.toThrow( - new InvalidAddressOrEnsError(), - ); + await expect(() => client.methods.getDao(daoAddress)).rejects.toThrow(); }); it("Should retrieve a list of Metadata details of DAO's, based on the given search params", async () => { - const context = new Context(contextParamsLocalChain); + const context = new Context(contextParamsMainnet); const client = new Client(context); const limit = 3; const params: IDaoQueryParams = { @@ -469,22 +466,26 @@ describe("Client", () => { const ctx = new Context(contextParamsMainnet); const client = new Client(ctx); const daoAddress = TEST_DAO_ADDRESS; - const balances = await client.methods.getDaoBalances(daoAddress); + const balances = await client.methods.getDaoBalances({ + daoAddressOrEns: daoAddress, + }); expect(Array.isArray(balances)).toBe(true); expect(balances === null).toBe(false); if (balances) { expect(balances.length > 0).toBe(true); - for (let i = 0; i < balances.length; i++) { - const balance = balances[i]; - expect(typeof balance.balance).toBe("bigint"); + for (const balance of balances) { expect(balance.updateDate instanceof Date).toBe(true); - if (balance.type === "erc20") { + if (balance.type === TokenType.NATIVE) { expect(typeof balance.balance).toBe("bigint"); - expect(typeof balance.decimals).toBe("number"); + } else { expect(typeof balance.address).toBe("string"); expect(balance.address).toMatch(/^0x[A-Fa-f0-9]{40}$/i); expect(typeof balance.name).toBe("string"); expect(typeof balance.symbol).toBe("string"); + if (balance.type === TokenType.ERC20) { + expect(typeof balance.balance).toBe("bigint"); + expect(typeof balance.decimals).toBe("number"); + } } } } @@ -493,13 +494,15 @@ describe("Client", () => { const ctx = new Context(contextParamsMainnet); const client = new Client(ctx); const daoAddress = TEST_NO_BALANCES_DAO_ADDRESS; - const balances = await client.methods.getDaoBalances(daoAddress); + const balances = await client.methods.getDaoBalances({ + daoAddressOrEns: daoAddress, + }); expect(Array.isArray(balances)).toBe(true); expect(balances?.length).toBe(0); }); it("Should get the transfers of a dao", async () => { - const ctx = new Context(contextParamsLocalChain); + const ctx = new Context(contextParamsMainnet); const client = new Client(ctx); const params: ITransferQueryParams = { daoAddressOrEns: TEST_DAO_ADDRESS, @@ -513,44 +516,25 @@ describe("Client", () => { if (transfers) { expect(transfers.length > 0).toBe(true); for (const transfer of transfers) { - expect(transfer.amount).toBeGreaterThan(BigInt(0)); - expect(typeof transfer.amount).toBe("bigint"); expect(transfer.creationDate).toBeInstanceOf(Date); + expect(transfer.from).toMatch(/^0x[A-Fa-f0-9]{40}$/i); + expect(transfer.to).toMatch(/^0x[A-Fa-f0-9]{40}$/i); expect(transfer.transactionId).toMatch(/^0x[A-Fa-f0-9]{64}$/i); if (transfer.tokenType === TokenType.NATIVE) { - if (transfer.type === TransferType.DEPOSIT) { - // ETH deposit - expect(isAddress(transfer.from)).toBe(true); - } else if (transfer.type === TransferType.WITHDRAW) { - // ETH withdraw - expect(isAddress(transfer.to)).toBe(true); - if (transfer.proposalId) { - expect(transfer.proposalId).toMatch( - /^0x[A-Fa-f0-9]{40}_0x[A-Fa-f0-9]{1,}$/i, - ); - } - } else { - fail("invalid transfer type"); - } - } else if (transfer.tokenType === TokenType.ERC20) { + expect(transfer.amount).toBeGreaterThan(BigInt(0)); + expect(typeof transfer.amount).toBe("bigint"); + } else { expect(isAddress(transfer.token.address)).toBe(true); - expect(typeof transfer.token.decimals).toBe("number"); + expect(typeof transfer.token.address).toBe("string"); + expect(transfer.token.address).toBeInstanceOf( + /^0x[A-Fa-f0-9]{40}$/i, + ); expect(typeof transfer.token.name).toBe("string"); expect(typeof transfer.token.symbol).toBe("string"); - if (transfer.type === TransferType.DEPOSIT) { - // ERC20 deposit - expect(isAddress(transfer.from)).toBe(true); - } else if (transfer.type === TransferType.WITHDRAW) { - // ERC20 withdraw - expect(isAddress(transfer.to)).toBe(true); - expect(transfer.proposalId).toMatch( - /^0x[A-Fa-f0-9]{40}_0x[A-Fa-f0-9]{1,}$/i, - ); - } else { - fail("invalid transfer type"); + if (transfer.tokenType === TokenType.ERC20) { + expect(typeof transfer.amount).toBe("bigint"); + expect(typeof transfer.token.decimals).toBe("number"); } - } else { - fail("invalid token type"); } } } else { @@ -558,7 +542,7 @@ describe("Client", () => { } }); it("Should get the transfers filtered by type", async () => { - const ctx = new Context(contextParamsLocalChain); + const ctx = new Context(contextParamsMainnet); const client = new Client(ctx); const transferType = TransferType.DEPOSIT; const params: ITransferQueryParams = { @@ -583,13 +567,13 @@ describe("Client", () => { test.todo( "Should return an empty array when getting the transfers of a DAO that does not exist", ); //, async () => { - // const ctx = new Context(contextParamsLocalChain); + // const ctx = new Context(contextParamsMainnet); // const client = new Client(ctx) - // const res = await client.methods.getTransfers(contextParamsLocalChain.dao) + // const res = await client.methods.getTransfers(contextParamsMainnet.dao) // expect(res.length).toBe(0) // }) test.todo("Should fail if the given ENS is invalid"); // async () => { - // const ctx = new Context(contextParamsLocalChain); + // const ctx = new Context(contextParamsMainnet); // const client = new Client(ctx) // // will fail when tested on local chain // await expect(client.methods.getTransfers("the.dao")).rejects.toThrow( diff --git a/modules/client/test/integration/constants.ts b/modules/client/test/integration/constants.ts index c72d074f3..7cea8f028 100644 --- a/modules/client/test/integration/constants.ts +++ b/modules/client/test/integration/constants.ts @@ -39,7 +39,7 @@ const grapqhlEndpoints = { working: [ { url: - "https://subgraph.satsuma-prod.com/qHR2wGfc5RLi6/aragon/core-goerli/version/v0.7.1-alpha/api", + "https://subgraph.satsuma-prod.com/qHR2wGfc5RLi6/aragon/core-goerli/version/v0.7.2-alpha/api", }, ], failing: [{ url: "https://bad-url-gateway.io/" }], diff --git a/modules/client/test/integration/tokenVoting-client/methods.test.ts b/modules/client/test/integration/tokenVoting-client/methods.test.ts index a88d52cc3..25edd680b 100644 --- a/modules/client/test/integration/tokenVoting-client/methods.test.ts +++ b/modules/client/test/integration/tokenVoting-client/methods.test.ts @@ -19,6 +19,7 @@ import { ProposalSortBy, ProposalStatus, SortDirection, + TokenType, TokenVotingClient, VoteProposalStep, VoteValues, @@ -81,9 +82,7 @@ describe("Token Voting Client", () => { // Helpers async function buildDaos() { const daoEntries: Array<{ dao: string; plugin: string }> = []; - daoEntries.push( - await buildTokenVotingDAO(repoAddr, VotingMode.STANDARD), - ); + daoEntries.push(await buildTokenVotingDAO(repoAddr, VotingMode.STANDARD)); daoEntries.push( await buildTokenVotingDAO(repoAddr, VotingMode.EARLY_EXECUTION), ); @@ -121,9 +120,7 @@ describe("Token Voting Client", () => { }, }; - const ipfsUri = await client.methods.pinMetadata( - metadata, - ); + const ipfsUri = await client.methods.pinMetadata(metadata); const endDate = new Date(Date.now() + 60 * 60 * 1000 + 10 * 1000); const proposalParams: ICreateProposalParams = { @@ -134,11 +131,7 @@ describe("Token Voting Client", () => { endDate, }; - for await ( - const step of client.methods.createProposal( - proposalParams, - ) - ) { + for await (const step of client.methods.createProposal(proposalParams)) { switch (step.key) { case ProposalCreationSteps.CREATING: expect(typeof step.txHash).toBe("string"); @@ -147,7 +140,7 @@ describe("Token Voting Client", () => { case ProposalCreationSteps.DONE: expect(typeof step.proposalId).toBe("number"); return step.proposalId; - // TODO fix with new proposalId format + // TODO fix with new proposalId format // expect(step.proposalId).toMatch(/^0x[A-Fa-f0-9]{64}$/i); default: throw new Error( @@ -180,8 +173,7 @@ describe("Token Voting Client", () => { break; default: throw new Error( - "Unexpected vote proposal step: " + - Object.keys(step).join(", "), + "Unexpected vote proposal step: " + Object.keys(step).join(", "), ); } } @@ -422,7 +414,9 @@ describe("Token Voting Client", () => { proposalId, }; for await ( - const step of client.methods.executeProposal(executeParams) + const step of client.methods.executeProposal( + executeParams, + ) ) { switch (step.key) { case ExecuteProposalStep.EXECUTING: @@ -466,7 +460,9 @@ describe("Token Voting Client", () => { proposalId, }; for await ( - const step of client.methods.executeProposal(executeParams) + const step of client.methods.executeProposal( + executeParams, + ) ) { switch (step.key) { case ExecuteProposalStep.EXECUTING: @@ -513,7 +509,9 @@ describe("Token Voting Client", () => { proposalId, }; for await ( - const step of client.methods.executeProposal(executeParams) + const step of client.methods.executeProposal( + executeParams, + ) ) { switch (step.key) { case ExecuteProposalStep.EXECUTING: @@ -562,10 +560,12 @@ describe("Token Voting Client", () => { title: "Title", summary: "Summary", description: "Description", - resources: [{ - name: "Name", - url: "url", - }], + resources: [ + { + name: "Name", + url: "url", + }, + ], }), ), ); @@ -638,10 +638,8 @@ describe("Token Voting Client", () => { expect(typeof proposal.token.symbol).toBe("string"); expect(typeof proposal.token.address).toBe("string"); expect(proposal.token.address).toMatch(/^0x[A-Fa-f0-9]{40}$/i); - if ("decimals" in proposal.token) { + if (proposal.token.type === TokenType.ERC20) { expect(typeof proposal.token.decimals).toBe("number"); - } else if ("baseUri" in proposal.token) { - expect(typeof proposal.token.baseUri).toBe("string"); } } expect(typeof proposal.usedVotingWeight).toBe("bigint"); @@ -655,6 +653,7 @@ describe("Token Voting Client", () => { expect(typeof vote.vote).toBe("number"); } expect(typeof vote.weight).toBe("bigint"); + expect(typeof vote.voteReplaced).toBe("boolean"); } if (proposal.executionTxHash) { expect(proposal.executionTxHash).toMatch(/^0x[A-Fa-f0-9]{64}$/i); diff --git a/modules/common/package.json b/modules/common/package.json index c78f104eb..b2767c409 100644 --- a/modules/common/package.json +++ b/modules/common/package.json @@ -55,4 +55,4 @@ "typescript": "^4.6.2" }, "dependencies": {} -} +} \ No newline at end of file