From a4942c0f6b6d6bc842abdcef86ee1bcebb919c2e Mon Sep 17 00:00:00 2001 From: Nils Date: Fri, 21 Mar 2025 14:03:23 +0100 Subject: [PATCH 1/3] dump --- src/constants/v2Addrs.ts | 14 +++ src/contracts/ve.ts | 179 +++++++++++++++++++++++++++++++++++++++ src/contracts/voter.ts | 31 +++++++ src/types/governance.ts | 119 ++++++++++++++++++++++++++ 4 files changed, 343 insertions(+) create mode 100644 src/contracts/ve.ts create mode 100644 src/contracts/voter.ts create mode 100644 src/types/governance.ts diff --git a/src/constants/v2Addrs.ts b/src/constants/v2Addrs.ts index 592d70a..c610118 100644 --- a/src/constants/v2Addrs.ts +++ b/src/constants/v2Addrs.ts @@ -53,3 +53,17 @@ export const MULTICALL_ADDRESS: AddressMap = { [ChainId.BUILDNET]: 'AS1yphCWi7gychZWYPpqrKDiGb6ZacRoji8YYMLHtQ2TSuuQFqLC', [ChainId.MAINNET]: 'AS1FJrNBtZ5oXK9y6Wcmiio5AV6rR2UopqqdQWhBH4Fss9JNMySm' } + +/** + * DEX governance SDK + */ + +export const VOTING_ESCROW_ADDRESS: AddressMap = { + [ChainId.BUILDNET]: '', + [ChainId.MAINNET]: '' +} + +export const VOTER_ADDRESS: AddressMap = { + [ChainId.BUILDNET]: '', + [ChainId.MAINNET]: '' +} diff --git a/src/contracts/ve.ts b/src/contracts/ve.ts new file mode 100644 index 0000000..ed6a08c --- /dev/null +++ b/src/contracts/ve.ts @@ -0,0 +1,179 @@ +import { GlobalPoint, LockedBalance, UserPoint } from '../types/governance' +import { IBaseContract } from './base' +import { Args, bytesToStr, byteToBool, U64 } from '@massalabs/massa-web3' + +export class IVotingEscrow extends IBaseContract { + async ownerOf(tokenId: number): Promise { + return this.extract(['idToOwner::' + tokenId]).then((r) => { + if (!r[0].length) throw new Error('Not found') + return bytesToStr(r[0]) + }) + } + async balanceOf(user: string): Promise { + return this.extract(['ownerToNFTokenCount::' + user]).then((r) => { + if (!r[0].length) throw new Error('Not found') + return Number(U64.fromBytes(r[0])) + }) + } + async getApproved(tokenId: number): Promise { + return this.extract(['idToApprovals::' + tokenId]).then((r) => { + if (!r[0].length) throw new Error('Not found') + return bytesToStr(r[0]) + }) + } + async isApprovedForAll(owner: string, operator: string): Promise { + return this.extract(['ownerToOperators::' + owner + operator]).then((r) => { + if (!r[0].length) throw new Error('Not found') + return byteToBool(r[0]) + }) + } + async isApprovedOrOwner(spender: string, tokenId: number): Promise { + return this.read({ + targetFunction: 'isApprovedOrOwner', + parameter: new Args() + .addString(spender) + .addU64(BigInt(tokenId)) + .serialize() + }).then((r) => byteToBool(r.value)) + } + + async locked(tokenId: number): Promise { + return this.read({ + targetFunction: 'locked', + parameter: new Args().addU64(BigInt(tokenId)).serialize() + }).then((r) => new LockedBalance().deserialize(r.value).instance) + } + async userPointHistory(tokenId: number, loc: number): Promise { + return this.read({ + targetFunction: 'userPointHistory', + parameter: new Args() + .addU64(BigInt(tokenId)) + .addU64(BigInt(loc)) + .serialize() + }).then((r) => new UserPoint().deserialize(r.value).instance) + } + async pointHistory(loc: number): Promise { + return this.read({ + targetFunction: 'pointHistory', + parameter: new Args().addU64(BigInt(loc)).serialize() + }).then((r) => new GlobalPoint().deserialize(r.value).instance) + } + async balanceOfNFT(tokenId: number): Promise { + return this.read({ + targetFunction: 'balanceOfNFT', + parameter: new Args().addU64(BigInt(tokenId)).serialize() + }).then((r) => BigInt(U64.fromBytes(r.value))) + } + async balanceOfNFTAt(tokenId: number, timestamp: number): Promise { + return this.read({ + targetFunction: 'balanceOfNFTAt', + parameter: new Args() + .addU64(BigInt(tokenId)) + .addU64(BigInt(timestamp)) + .serialize() + }).then((r) => BigInt(U64.fromBytes(r.value))) + } + async totalSupply(): Promise { + return this.read({ + targetFunction: 'totalSupply', + parameter: new Args().serialize() + }).then((r) => BigInt(U64.fromBytes(r.value))) + } + async totalSupplyAt(timestamp: number): Promise { + return this.read({ + targetFunction: 'totalSupplyAt', + parameter: new Args().addU64(BigInt(timestamp)).serialize() + }).then((r) => BigInt(U64.fromBytes(r.value))) + } + async delegates(tokenId: number): Promise { + return this.read({ + targetFunction: 'delegates', + parameter: new Args().addU64(BigInt(tokenId)).serialize() + }).then((r) => Number(U64.fromBytes(r.value))) + } + + async approve(to: string, tokenId: number): Promise { + return this.call({ + targetFunction: 'approve', + parameter: new Args().addString(to).addU64(BigInt(tokenId)).serialize() + }) + } + async setApprovalForAll( + operator: string, + approved: boolean + ): Promise { + return this.call({ + targetFunction: 'setApprovalForAll', + parameter: new Args().addString(operator).addBool(approved).serialize() + }) + } + async transferFrom( + from: string, + to: string, + tokenId: number + ): Promise { + return this.call({ + targetFunction: 'transferFrom', + parameter: new Args() + .addString(from) + .addString(to) + .addU64(BigInt(tokenId)) + .serialize() + }) + } + // async safeTransferFrom(from: string, to: string, tokenId: number): Promise {} + depositFor(tokenId: number, amount: bigint): Promise { + return this.call({ + targetFunction: 'depositFor', + parameter: new Args().addU64(BigInt(tokenId)).addU256(amount).serialize() + }) + } + createLock(amount: bigint, duration: number): Promise { + return this.call({ + targetFunction: 'createLock', + parameter: new Args().addU256(amount).addU64(BigInt(duration)).serialize() + }) + } + increaseAmount(tokenId: number, amount: bigint): Promise { + return this.call({ + targetFunction: 'increaseAmount', + parameter: new Args().addU64(BigInt(tokenId)).addU256(amount).serialize() + }) + } + increaseUnlockTime(tokenId: number, lockDuration: number): Promise { + return this.call({ + targetFunction: 'increaseUnlockTime', + parameter: new Args() + .addU64(BigInt(tokenId)) + .addU64(BigInt(lockDuration)) + .serialize() + }) + } + withdraw(tokenId: number): Promise { + return this.call({ + targetFunction: 'withdraw', + parameter: new Args().addU64(BigInt(tokenId)).serialize() + }) + } + lockPermanent(tokenId: number): Promise { + return this.call({ + targetFunction: 'lockPermanent', + parameter: new Args().addU64(BigInt(tokenId)).serialize() + }) + } + unlockPermanent(tokenId: number): Promise { + return this.call({ + targetFunction: 'unlockPermanent', + parameter: new Args().addU64(BigInt(tokenId)).serialize() + }) + } + delegate(delegator: number, delegatee: number): Promise { + return this.call({ + targetFunction: 'delegate', + parameter: new Args() + .addU64(BigInt(delegator)) + .addU64(BigInt(delegatee)) + .serialize() + }) + } +} diff --git a/src/contracts/voter.ts b/src/contracts/voter.ts new file mode 100644 index 0000000..ae8bcf5 --- /dev/null +++ b/src/contracts/voter.ts @@ -0,0 +1,31 @@ +import { IBaseContract } from './base' +import { Args, ArrayTypes, U64 } from '@massalabs/massa-web3' + +export class IVoter extends IBaseContract { + async lastVoted(tokenIds: number[]): Promise { + const bs = tokenIds.map((id: number) => `lastVoted::${id}`) + return this.extract(bs).then((r) => { + const lastVoted: number[] = [] + r.forEach((item) => { + if (!item?.length) return + lastVoted.push(Number(U64.fromBytes(item))) + }) + return lastVoted + }) + } + + vote( + tokenId: number, + poolVote: string[], + weights: bigint[] + ): Promise { + return this.call({ + targetFunction: 'vote', + parameter: new Args() + .addU64(BigInt(tokenId)) + .addArray(poolVote, ArrayTypes.STRING) + .addArray(weights, ArrayTypes.U256) + .serialize() + }) + } +} diff --git a/src/types/governance.ts b/src/types/governance.ts new file mode 100644 index 0000000..224c310 --- /dev/null +++ b/src/types/governance.ts @@ -0,0 +1,119 @@ +import { Args, IDeserializedResult, ISerializable } from '@massalabs/massa-web3' + +export class Checkpoint implements ISerializable { + constructor( + public fromTimestamp: number = 0, + public owner: string = '', + public delegatedBalance: bigint = 0n, + public delegatee: number = 0 + ) {} + + serialize(): Uint8Array { + return new Args() + .addU64(BigInt(this.fromTimestamp)) + .addString(this.owner) + .addU256(this.delegatedBalance) + .addU64(BigInt(this.delegatee)) + .serialize() + } + + deserialize(data: Uint8Array, offset = 0): IDeserializedResult { + const args = new Args(data, offset) + this.fromTimestamp = Number(args.nextU64()) + this.owner = args.nextString() + this.delegatedBalance = args.nextU256() + this.delegatee = Number(args.nextU64()) + + return { instance: this, offset: args.getOffset() } + } +} + +export class LockedBalance implements ISerializable { + constructor( + public amount: number = 0, + public end: number = 0, + public isPermanent: boolean = false + ) {} + + serialize(): Uint8Array { + return new Args() + .addI128(BigInt(this.amount)) + .addU64(BigInt(this.end)) + .addBool(this.isPermanent) + .serialize() + } + + deserialize( + data: Uint8Array, + offset = 0 + ): IDeserializedResult { + const args = new Args(data, offset) + this.amount = Number(args.nextI128()) + this.end = Number(args.nextU64()) + this.isPermanent = args.nextBool() + + return { instance: this, offset: args.getOffset() } + } +} + +export class UserPoint implements ISerializable { + constructor( + public bias: bigint = 0n, + public slope: bigint = 0n, // # -dweight / dt + public ts: number = 0, + public blk: number = 0, // block + public permanent: bigint = 0n + ) {} + + serialize(): Uint8Array { + return new Args() + .addI128(this.bias) + .addI128(this.slope) + .addU64(BigInt(this.ts)) + .addU64(BigInt(this.blk)) + .addU256(this.permanent) + .serialize() + } + + deserialize(data: Uint8Array, offset = 0): IDeserializedResult { + const args = new Args(data, offset) + this.bias = args.nextI128() + this.slope = args.nextI128() + this.ts = Number(args.nextU64()) + this.blk = Number(args.nextU64()) + this.permanent = args.nextU256() + + return { instance: this, offset: args.getOffset() } + } +} + +export class GlobalPoint implements ISerializable { + constructor( + public bias: bigint = 0n, + public slope: bigint = 0n, // # -dweight / dt + public ts: number = 0, + public blk: number = 0, // block + public permanentLockBalance: bigint = 0n + ) {} + + serialize(): Uint8Array { + return new Args() + .addI128(this.bias) + .addI128(this.slope) + .addU64(BigInt(this.ts)) + .addU64(BigInt(this.blk)) + .addU256(this.permanentLockBalance) + .serialize() + } + + deserialize(data: Uint8Array, offset = 0): IDeserializedResult { + const args = new Args(data, offset) + this.bias = args.nextI128() + this.slope = args.nextI128() + this.ts = Number(args.nextU64()) + this.blk = Number(args.nextU64()) + this.permanentLockBalance = args.nextU256() + + return { instance: this, offset: args.getOffset() } + } +} From 11342427f3e015746ae56864abd0fc2ee3579318 Mon Sep 17 00:00:00 2001 From: zzkk77xx Date: Tue, 16 Sep 2025 15:00:13 +0200 Subject: [PATCH 2/3] fix --- src/contracts/ve.ts | 12 ++++++------ src/contracts/voter.ts | 2 +- src/types/governance.ts | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/contracts/ve.ts b/src/contracts/ve.ts index ed6a08c..a83f768 100644 --- a/src/contracts/ve.ts +++ b/src/contracts/ve.ts @@ -1,6 +1,6 @@ import { GlobalPoint, LockedBalance, UserPoint } from '../types/governance' import { IBaseContract } from './base' -import { Args, bytesToStr, byteToBool, U64 } from '@massalabs/massa-web3' +import { Args, bytesToStr, byteToBool, U64, U256 } from '@massalabs/massa-web3' export class IVotingEscrow extends IBaseContract { async ownerOf(tokenId: number): Promise { @@ -62,7 +62,7 @@ export class IVotingEscrow extends IBaseContract { return this.read({ targetFunction: 'balanceOfNFT', parameter: new Args().addU64(BigInt(tokenId)).serialize() - }).then((r) => BigInt(U64.fromBytes(r.value))) + }).then((r) => U256.fromBytes(r.value)) } async balanceOfNFTAt(tokenId: number, timestamp: number): Promise { return this.read({ @@ -71,19 +71,19 @@ export class IVotingEscrow extends IBaseContract { .addU64(BigInt(tokenId)) .addU64(BigInt(timestamp)) .serialize() - }).then((r) => BigInt(U64.fromBytes(r.value))) + }).then((r) => U256.fromBytes(r.value)) } async totalSupply(): Promise { return this.read({ targetFunction: 'totalSupply', parameter: new Args().serialize() - }).then((r) => BigInt(U64.fromBytes(r.value))) + }).then((r) => U256.fromBytes(r.value)) } async totalSupplyAt(timestamp: number): Promise { return this.read({ targetFunction: 'totalSupplyAt', parameter: new Args().addU64(BigInt(timestamp)).serialize() - }).then((r) => BigInt(U64.fromBytes(r.value))) + }).then((r) => U256.fromBytes(r.value)) } async delegates(tokenId: number): Promise { return this.read({ @@ -121,7 +121,7 @@ export class IVotingEscrow extends IBaseContract { .serialize() }) } - // async safeTransferFrom(from: string, to: string, tokenId: number): Promise {} + depositFor(tokenId: number, amount: bigint): Promise { return this.call({ targetFunction: 'depositFor', diff --git a/src/contracts/voter.ts b/src/contracts/voter.ts index ae8bcf5..a49767e 100644 --- a/src/contracts/voter.ts +++ b/src/contracts/voter.ts @@ -1,5 +1,5 @@ import { IBaseContract } from './base' -import { Args, ArrayTypes, U64 } from '@massalabs/massa-web3' +import { Args, U64, ArrayTypes } from '@massalabs/massa-web3' export class IVoter extends IBaseContract { async lastVoted(tokenIds: number[]): Promise { diff --git a/src/types/governance.ts b/src/types/governance.ts index 224c310..b245b74 100644 --- a/src/types/governance.ts +++ b/src/types/governance.ts @@ -30,7 +30,7 @@ export class Checkpoint implements ISerializable { export class LockedBalance implements ISerializable { constructor( - public amount: number = 0, + public amount: bigint = 0n, public end: number = 0, public isPermanent: boolean = false ) {} @@ -48,7 +48,7 @@ export class LockedBalance implements ISerializable { offset = 0 ): IDeserializedResult { const args = new Args(data, offset) - this.amount = Number(args.nextI128()) + this.amount = args.nextI128() this.end = Number(args.nextU64()) this.isPermanent = args.nextBool() From 3c6bee5f60da5e0ea8b47dc59a8b1bc0dec6a566 Mon Sep 17 00:00:00 2001 From: zzkk77xx Date: Wed, 17 Sep 2025 13:29:17 +0200 Subject: [PATCH 3/3] add mainnet addresses & remove vote callSC --- src/constants/v2Addrs.ts | 4 ++-- src/contracts/voter.ts | 17 +---------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/constants/v2Addrs.ts b/src/constants/v2Addrs.ts index c610118..b4e881a 100644 --- a/src/constants/v2Addrs.ts +++ b/src/constants/v2Addrs.ts @@ -60,10 +60,10 @@ export const MULTICALL_ADDRESS: AddressMap = { export const VOTING_ESCROW_ADDRESS: AddressMap = { [ChainId.BUILDNET]: '', - [ChainId.MAINNET]: '' + [ChainId.MAINNET]: 'AS1q76iSMJ8Dj5gVBVK26y11yuFi9eVzUmTzwf5ANgoypMVcNjXj' } export const VOTER_ADDRESS: AddressMap = { [ChainId.BUILDNET]: '', - [ChainId.MAINNET]: '' + [ChainId.MAINNET]: 'AS1rg37d1cFXrSXbEaKbGPBKRXahshk6VgvwJXjg48MbyuwM1ea6' } diff --git a/src/contracts/voter.ts b/src/contracts/voter.ts index a49767e..384736a 100644 --- a/src/contracts/voter.ts +++ b/src/contracts/voter.ts @@ -1,5 +1,5 @@ import { IBaseContract } from './base' -import { Args, U64, ArrayTypes } from '@massalabs/massa-web3' +import { U64 } from '@massalabs/massa-web3' export class IVoter extends IBaseContract { async lastVoted(tokenIds: number[]): Promise { @@ -13,19 +13,4 @@ export class IVoter extends IBaseContract { return lastVoted }) } - - vote( - tokenId: number, - poolVote: string[], - weights: bigint[] - ): Promise { - return this.call({ - targetFunction: 'vote', - parameter: new Args() - .addU64(BigInt(tokenId)) - .addArray(poolVote, ArrayTypes.STRING) - .addArray(weights, ArrayTypes.U256) - .serialize() - }) - } }