Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add createEvmScript for new-vote #247

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@curvefi/api",
"version": "2.53.12",
"version": "2.54.0",
"description": "JavaScript library for curve.fi",
"main": "lib/index.js",
"author": "Macket",
Expand Down
74 changes: 74 additions & 0 deletions src/constants/dao/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {IDict} from "../../interfaces";
import gaugeControllerABI from "../abis/gaugecontroller.json" assert { type: 'json' };
import votingEscrowABI from '../abis/votingescrow.json' assert { type: 'json' };

export const poolActions = [
'commit_new_fee',
'ramp_A',
'commit_transfer_ownership',
'withdraw_admin_fees',
'unkill_me',
'apply_transfer_ownership',
'revert_transfer_ownership',
'apply_new_fee',
'stop_ramp_A',
'revert_new_parameters',
]

export const DaoAbiDictionaries: Record<string, IDict<any>> = {
pools: {
'commit_new_fee': undefined,
'ramp_A': undefined,
'commit_transfer_ownership': undefined,
'withdraw_admin_fees': undefined,
'unkill_me': undefined,
'apply_transfer_ownership': undefined,
'revert_transfer_ownership': undefined,
'apply_new_fee': undefined,
'stop_ramp_A': undefined,
'revert_new_parameters': undefined,
},
gauges: {
'commit_transfer_ownership': gaugeControllerABI,
'add_type': gaugeControllerABI,
'add_gauge': gaugeControllerABI,
'change_type_weight': gaugeControllerABI,
'change_gauge_weight': gaugeControllerABI,
'apply_transfer_ownership': gaugeControllerABI,
},
member: {
'mint': undefined,
'burn': undefined,
},
escrow: {
'commit_transfer_ownership': votingEscrowABI,
'commit_smart_wallet_checker': votingEscrowABI,
'apply_transfer_ownership': votingEscrowABI,
'apply_smart_wallet_checker': votingEscrowABI,
},
poolProxy: {
'commit_set_admins': undefined,
'set_burner': undefined,
'apply_set_admins': undefined,
},
registry: {
'add_pool': undefined,
'add_pool_without_underlying': undefined,
'remove_pool': undefined,
'set_returns_none': undefined,
'set_gas_estimate_contract': undefined,
'set_calculator': undefined,
'set_burner': undefined,
'apply_set_admins': undefined,
'commit_transfer_ownership': undefined,
'apply_transfer_ownership': undefined,
'revert_transfer_ownership': undefined,
'claim_token_balance': undefined,
'claim_eth_balance': undefined,
},
vesting: {
'fund_individual': undefined,
'toggle_disable': undefined,
'disable_can_disable': undefined,
},
}
83 changes: 82 additions & 1 deletion src/dao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { Contract } from "ethers";
import { _getAllGauges, _getDaoProposalList, _getDaoProposal } from './external-api.js';
import {
_getAddress,
DIGas, ensureAllowance, ensureAllowanceEstimateGas, hasAllowance,
DIGas,
ensureAllowance,
ensureAllowanceEstimateGas,
hasAllowance,
mulBy1_3,
parseUnits,
smartNumber,
Expand All @@ -17,8 +20,14 @@ import {
IDaoProposalUserListItem,
IDaoProposal,
IDict,
IDaoAction,
TDaoActionType,
TDaoAvailableMethodsOfPool,
} from './interfaces';
import feeDistributorViewABI from "./constants/abis/fee_distributor_view.json" assert { type: 'json' };
import {poolActions} from "./constants/dao/actions";
import gaugeControllerABI from "./constants/abis/gaugecontroller.json";
import axios from "axios";


// ----------------- Refactored boosting stuff -----------------
Expand Down Expand Up @@ -382,3 +391,75 @@ export const voteForProposalEstimateGas = async (type: "PARAMETER" | "OWNERSHIP"
export const voteForProposal = async (type: "PARAMETER" | "OWNERSHIP", id: number, support: boolean): Promise<string> => {
return await _voteForProposal(type, id, support, false) as string;
}

export const getAvailableMethodsOfPool = (address: string):TDaoAvailableMethodsOfPool => {
const result: TDaoAvailableMethodsOfPool = {};
poolActions.forEach((item) => {
if(curve.contracts[address].contract.interface.fragments.find((method: any) => method.name === item)) {
result[item] = true;
} else {
result[item] = false;
}
})

return result;
}

export const createActionForVote = (actionType: TDaoActionType, address: string, method: string, args: any[]): IDaoAction => {
if(actionType === 'pools') {
if(!getAvailableMethodsOfPool(address)[method]) {
throw Error(`Method ${{method}} is not available for this pool`);
} else {
return {
address,
contract: curve.contracts[address].contract,
method,
args,
}
}
}
if(actionType === 'gauges') {
return {
address,
contract: new Contract(address, gaugeControllerABI, curve.signer || curve.provider),
method,
args,
}
}

throw Error('Unavailable pool type')
}

export const createEvmScript = async (address: string, abi: any, action: IDaoAction) => {
const agent = new Contract(address, abi, curve.signer || curve.provider)
const zeroPad = (num: string, places: number) =>
String(num).padStart(places, "0");

let evm_script = "0x00000001"

const contract = action.contract;
const call_data = contract.interface.encodeFunctionData(action.method, [...action.args])

const agent_calldata = agent.interface
.encodeFunctionData("execute", [action.address, 0, call_data])
.substring(2);

const length = zeroPad((Math.floor(agent_calldata.length) / 2).toString(16), 8);

evm_script = `${evm_script}${address.substring(2)}${length}${agent_calldata}`;

return evm_script
}

export const createVoteDescription = async (description: string) => {
const vote_description = description.replace(/(\r\n|\n|\r)/gm, "");
const vote_data = {
text: vote_description,
};

const data = new FormData();
data.append("file", JSON.stringify(vote_data));
const url = `https://ipfs.infura.io:5001/api/v0/add`;
const response = await axios.post(url, data);
return response.data.Hash;
}
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ import {
userProposalVotes,
voteForProposalEstimateGas,
voteForProposal,
createEvmScript,
createVoteDescription,
createActionForVote,
} from "./dao.js";

async function init (
Expand Down Expand Up @@ -356,6 +359,8 @@ const curve = {
userProposalVotes,
// Transaction methods
voteForProposal,
createEvmScript,
createVoteDescription,

estimateGas: {
// --- CRV lock ---
Expand Down
13 changes: 12 additions & 1 deletion src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,15 @@ export interface IVolumeAndAPYs {
cryptoVolume: number,
cryptoShare: number,
poolsData: IVolumeAndAPYsPoolData[],
}
}

export type TDaoActionType = 'pools' | 'gauges'

export type TDaoAvailableMethodsOfPool = Record<string, boolean>

export interface IDaoAction {
address: string,
contract: Contract,
method: string,
args: any[],
}
5 changes: 4 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
// "incremental": true, /* Enable incremental compilation */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"lib": ["ES2020"], /* Specify library files to be included in the compilation. */
"lib": [
"ES2020",
"dom"
], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
Expand Down