diff --git a/.gitmodules b/.gitmodules index 4b139dbb..72defcb2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "futarchy-ts"] - path = futarchy-ts + path = packages/futarchy-ts url = https://github.com/metaDAOproject/futarchy-ts diff --git a/futarchy-ts b/futarchy-ts deleted file mode 160000 index 5ea34679..00000000 --- a/futarchy-ts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5ea346797013dc28aea87d43b3caa3b0d5894635 diff --git a/packages/futarchy-ts/.gitignore b/packages/futarchy-ts/.gitignore new file mode 100644 index 00000000..40b878db --- /dev/null +++ b/packages/futarchy-ts/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/packages/futarchy-ts/README.md b/packages/futarchy-ts/README.md new file mode 100644 index 00000000..2362504f --- /dev/null +++ b/packages/futarchy-ts/README.md @@ -0,0 +1,3 @@ +# futarchy-ts + +The Meta-DAO Futarchy Typescript SDK diff --git a/packages/futarchy-ts/lib/constants.ts b/packages/futarchy-ts/lib/constants.ts new file mode 100644 index 00000000..cd890e6e --- /dev/null +++ b/packages/futarchy-ts/lib/constants.ts @@ -0,0 +1,32 @@ +import { PublicKey } from '@solana/web3.js'; +import { BN } from '@coral-xyz/anchor'; +import { AutocratProgram, ProgramVersion } from './types'; + + +export const OPENBOOK_PROGRAM_ID = new PublicKey('opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb'); +export const OPENBOOK_TWAP_PROGRAM_ID = new PublicKey( + 'TWAPrdhADy2aTKN5iFZtNnkQYXERD9NvKjPFVPMSCNN', +); + +export const NUMERAL_FORMAT = '0,0.00'; +export const BASE_FORMAT = '0,0'; +export const SLOTS_PER_10_SECS: number = 25; +export const TEN_DAYS_IN_SLOTS: number = 10 * 24 * 60 * 6 * SLOTS_PER_10_SECS; +export const QUOTE_LOTS = 0.0001; +export const BN_0 = new BN(0); + +const AUTOCRAT_V0_IDL: AutocratProgram = require('./idl/autocrat_v0.json'); +const AUTOCRAT_V0_1_IDL: AutocratProgram = require('./idl/autocrat_v0.1.json'); + +export const AUTOCRAT_VERSIONS: ProgramVersion[] = [ + { + label: 'V0.1', + programId: new PublicKey('metaX99LHn3A7Gr7VAcCfXhpfocvpMpqQ3eyp3PGUUq'), + idl: AUTOCRAT_V0_1_IDL, + }, + { + label: 'V0', + programId: new PublicKey('meta3cxKzFBmWYgCVozmvCQAS3y9b3fGxrG9HkHL7Wi'), + idl: AUTOCRAT_V0_IDL, + }, +]; diff --git a/packages/futarchy-ts/lib/idl/autocrat_v0.1.json b/packages/futarchy-ts/lib/idl/autocrat_v0.1.json new file mode 100644 index 00000000..77e8a953 --- /dev/null +++ b/packages/futarchy-ts/lib/idl/autocrat_v0.1.json @@ -0,0 +1,450 @@ +{ + "version": "0.1.0", + "name": "autocrat_v0", + "instructions": [ + { + "name": "initializeDao", + "accounts": [ + { + "name": "dao", + "isMut": true, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "metaMint", + "isMut": false, + "isSigner": false + }, + { + "name": "usdcMint", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializeProposal", + "accounts": [ + { + "name": "proposal", + "isMut": true, + "isSigner": true + }, + { + "name": "dao", + "isMut": true, + "isSigner": false + }, + { + "name": "daoTreasury", + "isMut": true, + "isSigner": false + }, + { + "name": "quoteVault", + "isMut": false, + "isSigner": false + }, + { + "name": "baseVault", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookPassMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookFailMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookTwapPassMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookTwapFailMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "proposer", + "isMut": true, + "isSigner": true + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "descriptionUrl", + "type": "string" + }, + { + "name": "instruction", + "type": { + "defined": "ProposalInstruction" + } + } + ] + }, + { + "name": "finalizeProposal", + "accounts": [ + { + "name": "proposal", + "isMut": true, + "isSigner": false + }, + { + "name": "openbookTwapPassMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookTwapFailMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "dao", + "isMut": false, + "isSigner": false + }, + { + "name": "baseVault", + "isMut": true, + "isSigner": false + }, + { + "name": "quoteVault", + "isMut": true, + "isSigner": false + }, + { + "name": "vaultProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "daoTreasury", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "updateDao", + "accounts": [ + { + "name": "dao", + "isMut": true, + "isSigner": false + }, + { + "name": "daoTreasury", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "daoParams", + "type": { + "defined": "UpdateDaoParams" + } + } + ] + } + ], + "accounts": [ + { + "name": "DAO", + "type": { + "kind": "struct", + "fields": [ + { + "name": "treasuryPdaBump", + "type": "u8" + }, + { + "name": "treasury", + "type": "publicKey" + }, + { + "name": "metaMint", + "type": "publicKey" + }, + { + "name": "usdcMint", + "type": "publicKey" + }, + { + "name": "proposalCount", + "type": "u32" + }, + { + "name": "lastProposalSlot", + "type": "u64" + }, + { + "name": "passThresholdBps", + "type": "u16" + }, + { + "name": "baseBurnLamports", + "type": "u64" + }, + { + "name": "burnDecayPerSlotLamports", + "type": "u64" + }, + { + "name": "slotsPerProposal", + "type": "u64" + }, + { + "name": "marketTakerFee", + "type": "i64" + }, + { + "name": "twapExpectedValue", + "type": "u64" + } + ] + } + }, + { + "name": "Proposal", + "type": { + "kind": "struct", + "fields": [ + { + "name": "number", + "type": "u32" + }, + { + "name": "proposer", + "type": "publicKey" + }, + { + "name": "descriptionUrl", + "type": "string" + }, + { + "name": "slotEnqueued", + "type": "u64" + }, + { + "name": "state", + "type": { + "defined": "ProposalState" + } + }, + { + "name": "instruction", + "type": { + "defined": "ProposalInstruction" + } + }, + { + "name": "openbookTwapPassMarket", + "type": "publicKey" + }, + { + "name": "openbookTwapFailMarket", + "type": "publicKey" + }, + { + "name": "openbookPassMarket", + "type": "publicKey" + }, + { + "name": "openbookFailMarket", + "type": "publicKey" + }, + { + "name": "baseVault", + "type": "publicKey" + }, + { + "name": "quoteVault", + "type": "publicKey" + } + ] + } + } + ], + "types": [ + { + "name": "ProposalInstruction", + "type": { + "kind": "struct", + "fields": [ + { + "name": "programId", + "type": "publicKey" + }, + { + "name": "accounts", + "type": { + "vec": { + "defined": "ProposalAccount" + } + } + }, + { + "name": "data", + "type": "bytes" + } + ] + } + }, + { + "name": "ProposalAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "type": "publicKey" + }, + { + "name": "isSigner", + "type": "bool" + }, + { + "name": "isWritable", + "type": "bool" + } + ] + } + }, + { + "name": "UpdateDaoParams", + "type": { + "kind": "struct", + "fields": [ + { + "name": "passThresholdBps", + "type": { + "option": "u16" + } + }, + { + "name": "baseBurnLamports", + "type": { + "option": "u64" + } + }, + { + "name": "burnDecayPerSlotLamports", + "type": { + "option": "u64" + } + }, + { + "name": "slotsPerProposal", + "type": { + "option": "u64" + } + }, + { + "name": "marketTakerFee", + "type": { + "option": "i64" + } + }, + { + "name": "twapExpectedValue", + "type": { + "option": "u64" + } + } + ] + } + }, + { + "name": "ProposalState", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Pending" + }, + { + "name": "Passed" + }, + { + "name": "Failed" + } + ] + } + } + ], + "errors": [ + { + "code": 6000, + "name": "InvalidMarket", + "msg": "Either the `pass_market` or the `fail_market`'s tokens doesn't match the vaults supplied" + }, + { + "code": 6001, + "name": "TWAPMarketTooOld", + "msg": "`TWAPMarket` must have an `initial_slot` within 50 slots of the proposal's `slot_enqueued`" + }, + { + "code": 6002, + "name": "TWAPMarketInvalidExpectedValue", + "msg": "`TWAPMarket` has the wrong `expected_value`" + }, + { + "code": 6003, + "name": "InvalidSettlementAuthority", + "msg": "One of the vaults has an invalid `settlement_authority`" + }, + { + "code": 6004, + "name": "ProposalTooYoung", + "msg": "Proposal is too young to be executed or rejected" + }, + { + "code": 6005, + "name": "MarketsTooYoung", + "msg": "Markets too young for proposal to be finalized" + }, + { + "code": 6006, + "name": "ProposalCannotPass", + "msg": "The market dictates that this proposal cannot pass" + }, + { + "code": 6007, + "name": "ProposalAlreadyFinalized", + "msg": "This proposal has already been finalized" + }, + { + "code": 6008, + "name": "InvalidVaultNonce", + "msg": "A conditional vault has an invalid nonce. A nonce should encode pass = 0 / fail = 1 in its most significant bit, base = 0 / quote = 1 in its second most significant bit, and the proposal number in least significant 32 bits" + } + ] +} \ No newline at end of file diff --git a/packages/futarchy-ts/lib/idl/autocrat_v0.1.ts b/packages/futarchy-ts/lib/idl/autocrat_v0.1.ts new file mode 100644 index 00000000..dcf207ec --- /dev/null +++ b/packages/futarchy-ts/lib/idl/autocrat_v0.1.ts @@ -0,0 +1,901 @@ +export type AutocratV0 = { + version: '0.1.0'; + name: 'autocrat_v0'; + instructions: [ + { + name: 'initializeDao'; + accounts: [ + { + name: 'dao'; + isMut: true; + isSigner: false; + }, + { + name: 'payer'; + isMut: true; + isSigner: true; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'metaMint'; + isMut: false; + isSigner: false; + }, + { + name: 'usdcMint'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'initializeProposal'; + accounts: [ + { + name: 'proposal'; + isMut: true; + isSigner: true; + }, + { + name: 'dao'; + isMut: true; + isSigner: false; + }, + { + name: 'daoTreasury'; + isMut: true; + isSigner: false; + }, + { + name: 'quoteVault'; + isMut: false; + isSigner: false; + }, + { + name: 'baseVault'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookPassMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookFailMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookTwapPassMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookTwapFailMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'proposer'; + isMut: true; + isSigner: true; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'descriptionUrl'; + type: 'string'; + }, + { + name: 'instruction'; + type: { + defined: 'ProposalInstruction'; + }; + }, + ]; + }, + { + name: 'finalizeProposal'; + accounts: [ + { + name: 'proposal'; + isMut: true; + isSigner: false; + }, + { + name: 'openbookTwapPassMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookTwapFailMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'dao'; + isMut: false; + isSigner: false; + }, + { + name: 'baseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'quoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'vaultProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'daoTreasury'; + isMut: true; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'updateDao'; + accounts: [ + { + name: 'dao'; + isMut: true; + isSigner: false; + }, + { + name: 'daoTreasury'; + isMut: false; + isSigner: true; + }, + ]; + args: [ + { + name: 'daoParams'; + type: { + defined: 'UpdateDaoParams'; + }; + }, + ]; + }, + ]; + accounts: [ + { + name: 'dao'; + type: { + kind: 'struct'; + fields: [ + { + name: 'treasuryPdaBump'; + type: 'u8'; + }, + { + name: 'treasury'; + type: 'publicKey'; + }, + { + name: 'metaMint'; + type: 'publicKey'; + }, + { + name: 'usdcMint'; + type: 'publicKey'; + }, + { + name: 'proposalCount'; + type: 'u32'; + }, + { + name: 'lastProposalSlot'; + type: 'u64'; + }, + { + name: 'passThresholdBps'; + type: 'u16'; + }, + { + name: 'baseBurnLamports'; + type: 'u64'; + }, + { + name: 'burnDecayPerSlotLamports'; + type: 'u64'; + }, + { + name: 'slotsPerProposal'; + type: 'u64'; + }, + { + name: 'marketTakerFee'; + type: 'i64'; + }, + { + name: 'twapExpectedValue'; + type: 'u64'; + }, + ]; + }; + }, + { + name: 'proposal'; + type: { + kind: 'struct'; + fields: [ + { + name: 'number'; + type: 'u32'; + }, + { + name: 'proposer'; + type: 'publicKey'; + }, + { + name: 'descriptionUrl'; + type: 'string'; + }, + { + name: 'slotEnqueued'; + type: 'u64'; + }, + { + name: 'state'; + type: { + defined: 'ProposalState'; + }; + }, + { + name: 'instruction'; + type: { + defined: 'ProposalInstruction'; + }; + }, + { + name: 'openbookTwapPassMarket'; + type: 'publicKey'; + }, + { + name: 'openbookTwapFailMarket'; + type: 'publicKey'; + }, + { + name: 'openbookPassMarket'; + type: 'publicKey'; + }, + { + name: 'openbookFailMarket'; + type: 'publicKey'; + }, + { + name: 'baseVault'; + type: 'publicKey'; + }, + { + name: 'quoteVault'; + type: 'publicKey'; + }, + ]; + }; + }, + ]; + types: [ + { + name: 'ProposalInstruction'; + type: { + kind: 'struct'; + fields: [ + { + name: 'programId'; + type: 'publicKey'; + }, + { + name: 'accounts'; + type: { + vec: { + defined: 'ProposalAccount'; + }; + }; + }, + { + name: 'data'; + type: 'bytes'; + }, + ]; + }; + }, + { + name: 'ProposalAccount'; + type: { + kind: 'struct'; + fields: [ + { + name: 'pubkey'; + type: 'publicKey'; + }, + { + name: 'isSigner'; + type: 'bool'; + }, + { + name: 'isWritable'; + type: 'bool'; + }, + ]; + }; + }, + { + name: 'UpdateDaoParams'; + type: { + kind: 'struct'; + fields: [ + { + name: 'passThresholdBps'; + type: { + option: 'u16'; + }; + }, + { + name: 'baseBurnLamports'; + type: { + option: 'u64'; + }; + }, + { + name: 'burnDecayPerSlotLamports'; + type: { + option: 'u64'; + }; + }, + { + name: 'slotsPerProposal'; + type: { + option: 'u64'; + }; + }, + { + name: 'marketTakerFee'; + type: { + option: 'i64'; + }; + }, + { + name: 'twapExpectedValue'; + type: { + option: 'u64'; + }; + }, + ]; + }; + }, + { + name: 'ProposalState'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Pending'; + }, + { + name: 'Passed'; + }, + { + name: 'Failed'; + }, + ]; + }; + }, + ]; + errors: [ + { + code: 6000; + name: 'InvalidMarket'; + msg: "Either the `pass_market` or the `fail_market`'s tokens doesn't match the vaults supplied"; + }, + { + code: 6001; + name: 'TWAPMarketTooOld'; + msg: "`TWAPMarket` must have an `initial_slot` within 50 slots of the proposal's `slot_enqueued`"; + }, + { + code: 6002; + name: 'TWAPMarketInvalidExpectedValue'; + msg: '`TWAPMarket` has the wrong `expected_value`'; + }, + { + code: 6003; + name: 'InvalidSettlementAuthority'; + msg: 'One of the vaults has an invalid `settlement_authority`'; + }, + { + code: 6004; + name: 'ProposalTooYoung'; + msg: 'Proposal is too young to be executed or rejected'; + }, + { + code: 6005; + name: 'MarketsTooYoung'; + msg: 'Markets too young for proposal to be finalized'; + }, + { + code: 6006; + name: 'ProposalCannotPass'; + msg: 'The market dictates that this proposal cannot pass'; + }, + { + code: 6007; + name: 'ProposalAlreadyFinalized'; + msg: 'This proposal has already been finalized'; + }, + { + code: 6008; + name: 'InvalidVaultNonce'; + msg: 'A conditional vault has an invalid nonce. A nonce should encode pass = 0 / fail = 1 in its most significant bit, base = 0 / quote = 1 in its second most significant bit, and the proposal number in least significant 32 bits'; + }, + ]; +}; + +export const IDL: AutocratV0 = { + version: '0.1.0', + name: 'autocrat_v0', + instructions: [ + { + name: 'initializeDao', + accounts: [ + { + name: 'dao', + isMut: true, + isSigner: false, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + { + name: 'metaMint', + isMut: false, + isSigner: false, + }, + { + name: 'usdcMint', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'initializeProposal', + accounts: [ + { + name: 'proposal', + isMut: true, + isSigner: true, + }, + { + name: 'dao', + isMut: true, + isSigner: false, + }, + { + name: 'daoTreasury', + isMut: true, + isSigner: false, + }, + { + name: 'quoteVault', + isMut: false, + isSigner: false, + }, + { + name: 'baseVault', + isMut: false, + isSigner: false, + }, + { + name: 'openbookPassMarket', + isMut: false, + isSigner: false, + }, + { + name: 'openbookFailMarket', + isMut: false, + isSigner: false, + }, + { + name: 'openbookTwapPassMarket', + isMut: false, + isSigner: false, + }, + { + name: 'openbookTwapFailMarket', + isMut: false, + isSigner: false, + }, + { + name: 'proposer', + isMut: true, + isSigner: true, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'descriptionUrl', + type: 'string', + }, + { + name: 'instruction', + type: { + defined: 'ProposalInstruction', + }, + }, + ], + }, + { + name: 'finalizeProposal', + accounts: [ + { + name: 'proposal', + isMut: true, + isSigner: false, + }, + { + name: 'openbookTwapPassMarket', + isMut: false, + isSigner: false, + }, + { + name: 'openbookTwapFailMarket', + isMut: false, + isSigner: false, + }, + { + name: 'dao', + isMut: false, + isSigner: false, + }, + { + name: 'baseVault', + isMut: true, + isSigner: false, + }, + { + name: 'quoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'vaultProgram', + isMut: false, + isSigner: false, + }, + { + name: 'daoTreasury', + isMut: true, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'updateDao', + accounts: [ + { + name: 'dao', + isMut: true, + isSigner: false, + }, + { + name: 'daoTreasury', + isMut: false, + isSigner: true, + }, + ], + args: [ + { + name: 'daoParams', + type: { + defined: 'UpdateDaoParams', + }, + }, + ], + }, + ], + accounts: [ + { + name: 'dao', + type: { + kind: 'struct', + fields: [ + { + name: 'treasuryPdaBump', + type: 'u8', + }, + { + name: 'treasury', + type: 'publicKey', + }, + { + name: 'metaMint', + type: 'publicKey', + }, + { + name: 'usdcMint', + type: 'publicKey', + }, + { + name: 'proposalCount', + type: 'u32', + }, + { + name: 'lastProposalSlot', + type: 'u64', + }, + { + name: 'passThresholdBps', + type: 'u16', + }, + { + name: 'baseBurnLamports', + type: 'u64', + }, + { + name: 'burnDecayPerSlotLamports', + type: 'u64', + }, + { + name: 'slotsPerProposal', + type: 'u64', + }, + { + name: 'marketTakerFee', + type: 'i64', + }, + { + name: 'twapExpectedValue', + type: 'u64', + }, + ], + }, + }, + { + name: 'proposal', + type: { + kind: 'struct', + fields: [ + { + name: 'number', + type: 'u32', + }, + { + name: 'proposer', + type: 'publicKey', + }, + { + name: 'descriptionUrl', + type: 'string', + }, + { + name: 'slotEnqueued', + type: 'u64', + }, + { + name: 'state', + type: { + defined: 'ProposalState', + }, + }, + { + name: 'instruction', + type: { + defined: 'ProposalInstruction', + }, + }, + { + name: 'openbookTwapPassMarket', + type: 'publicKey', + }, + { + name: 'openbookTwapFailMarket', + type: 'publicKey', + }, + { + name: 'openbookPassMarket', + type: 'publicKey', + }, + { + name: 'openbookFailMarket', + type: 'publicKey', + }, + { + name: 'baseVault', + type: 'publicKey', + }, + { + name: 'quoteVault', + type: 'publicKey', + }, + ], + }, + }, + ], + types: [ + { + name: 'ProposalInstruction', + type: { + kind: 'struct', + fields: [ + { + name: 'programId', + type: 'publicKey', + }, + { + name: 'accounts', + type: { + vec: { + defined: 'ProposalAccount', + }, + }, + }, + { + name: 'data', + type: 'bytes', + }, + ], + }, + }, + { + name: 'ProposalAccount', + type: { + kind: 'struct', + fields: [ + { + name: 'pubkey', + type: 'publicKey', + }, + { + name: 'isSigner', + type: 'bool', + }, + { + name: 'isWritable', + type: 'bool', + }, + ], + }, + }, + { + name: 'UpdateDaoParams', + type: { + kind: 'struct', + fields: [ + { + name: 'passThresholdBps', + type: { + option: 'u16', + }, + }, + { + name: 'baseBurnLamports', + type: { + option: 'u64', + }, + }, + { + name: 'burnDecayPerSlotLamports', + type: { + option: 'u64', + }, + }, + { + name: 'slotsPerProposal', + type: { + option: 'u64', + }, + }, + { + name: 'marketTakerFee', + type: { + option: 'i64', + }, + }, + { + name: 'twapExpectedValue', + type: { + option: 'u64', + }, + }, + ], + }, + }, + { + name: 'ProposalState', + type: { + kind: 'enum', + variants: [ + { + name: 'Pending', + }, + { + name: 'Passed', + }, + { + name: 'Failed', + }, + ], + }, + }, + ], + errors: [ + { + code: 6000, + name: 'InvalidMarket', + msg: "Either the `pass_market` or the `fail_market`'s tokens doesn't match the vaults supplied", + }, + { + code: 6001, + name: 'TWAPMarketTooOld', + msg: "`TWAPMarket` must have an `initial_slot` within 50 slots of the proposal's `slot_enqueued`", + }, + { + code: 6002, + name: 'TWAPMarketInvalidExpectedValue', + msg: '`TWAPMarket` has the wrong `expected_value`', + }, + { + code: 6003, + name: 'InvalidSettlementAuthority', + msg: 'One of the vaults has an invalid `settlement_authority`', + }, + { + code: 6004, + name: 'ProposalTooYoung', + msg: 'Proposal is too young to be executed or rejected', + }, + { + code: 6005, + name: 'MarketsTooYoung', + msg: 'Markets too young for proposal to be finalized', + }, + { + code: 6006, + name: 'ProposalCannotPass', + msg: 'The market dictates that this proposal cannot pass', + }, + { + code: 6007, + name: 'ProposalAlreadyFinalized', + msg: 'This proposal has already been finalized', + }, + { + code: 6008, + name: 'InvalidVaultNonce', + msg: 'A conditional vault has an invalid nonce. A nonce should encode pass = 0 / fail = 1 in its most significant bit, base = 0 / quote = 1 in its second most significant bit, and the proposal number in least significant 32 bits', + }, + ], +}; diff --git a/packages/futarchy-ts/lib/idl/autocrat_v0.json b/packages/futarchy-ts/lib/idl/autocrat_v0.json new file mode 100644 index 00000000..86bc554a --- /dev/null +++ b/packages/futarchy-ts/lib/idl/autocrat_v0.json @@ -0,0 +1,437 @@ +{ + "version": "0.1.0", + "name": "autocrat_v0", + "instructions": [ + { + "name": "initializeDao", + "accounts": [ + { + "name": "dao", + "isMut": true, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "metaMint", + "isMut": false, + "isSigner": false + }, + { + "name": "usdcMint", + "isMut": false, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "initializeProposal", + "accounts": [ + { + "name": "proposal", + "isMut": true, + "isSigner": true + }, + { + "name": "dao", + "isMut": true, + "isSigner": false + }, + { + "name": "daoTreasury", + "isMut": true, + "isSigner": false + }, + { + "name": "quoteVault", + "isMut": false, + "isSigner": false + }, + { + "name": "baseVault", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookPassMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookFailMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookTwapPassMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookTwapFailMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "proposer", + "isMut": true, + "isSigner": true + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "descriptionUrl", + "type": "string" + }, + { + "name": "instruction", + "type": { + "defined": "ProposalInstruction" + } + } + ] + }, + { + "name": "finalizeProposal", + "accounts": [ + { + "name": "proposal", + "isMut": true, + "isSigner": false + }, + { + "name": "openbookTwapPassMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookTwapFailMarket", + "isMut": false, + "isSigner": false + }, + { + "name": "dao", + "isMut": false, + "isSigner": false + }, + { + "name": "baseVault", + "isMut": true, + "isSigner": false + }, + { + "name": "quoteVault", + "isMut": true, + "isSigner": false + }, + { + "name": "vaultProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "daoTreasury", + "isMut": true, + "isSigner": false + } + ], + "args": [] + }, + { + "name": "setPassThresholdBps", + "accounts": [ + { + "name": "dao", + "isMut": true, + "isSigner": false + }, + { + "name": "daoTreasury", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "passThresholdBps", + "type": "u16" + } + ] + }, + { + "name": "setLastProposalSlot", + "accounts": [ + { + "name": "dao", + "isMut": true, + "isSigner": false + }, + { + "name": "daoTreasury", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "lastProposalSlot", + "type": "u64" + } + ] + }, + { + "name": "setBaseBurnLamports", + "accounts": [ + { + "name": "dao", + "isMut": true, + "isSigner": false + }, + { + "name": "daoTreasury", + "isMut": false, + "isSigner": true + } + ], + "args": [ + { + "name": "baseBurnLamports", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "DAO", + "type": { + "kind": "struct", + "fields": [ + { + "name": "metaMint", + "type": "publicKey" + }, + { + "name": "usdcMint", + "type": "publicKey" + }, + { + "name": "passThresholdBps", + "type": "u16" + }, + { + "name": "proposalCount", + "type": "u32" + }, + { + "name": "lastProposalSlot", + "type": "u64" + }, + { + "name": "baseBurnLamports", + "type": "u64" + }, + { + "name": "burnDecayPerSlotLamports", + "type": "u64" + }, + { + "name": "treasuryPdaBump", + "type": "u8" + }, + { + "name": "treasury", + "type": "publicKey" + } + ] + } + }, + { + "name": "Proposal", + "type": { + "kind": "struct", + "fields": [ + { + "name": "number", + "type": "u32" + }, + { + "name": "proposer", + "type": "publicKey" + }, + { + "name": "descriptionUrl", + "type": "string" + }, + { + "name": "slotEnqueued", + "type": "u64" + }, + { + "name": "state", + "type": { + "defined": "ProposalState" + } + }, + { + "name": "instruction", + "type": { + "defined": "ProposalInstruction" + } + }, + { + "name": "openbookTwapPassMarket", + "type": "publicKey" + }, + { + "name": "openbookTwapFailMarket", + "type": "publicKey" + }, + { + "name": "openbookPassMarket", + "type": "publicKey" + }, + { + "name": "openbookFailMarket", + "type": "publicKey" + }, + { + "name": "baseVault", + "type": "publicKey" + }, + { + "name": "quoteVault", + "type": "publicKey" + } + ] + } + } + ], + "types": [ + { + "name": "ProposalInstruction", + "type": { + "kind": "struct", + "fields": [ + { + "name": "programId", + "type": "publicKey" + }, + { + "name": "accounts", + "type": { + "vec": { + "defined": "ProposalAccount" + } + } + }, + { + "name": "data", + "type": "bytes" + } + ] + } + }, + { + "name": "ProposalAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pubkey", + "type": "publicKey" + }, + { + "name": "isSigner", + "type": "bool" + }, + { + "name": "isWritable", + "type": "bool" + } + ] + } + }, + { + "name": "ProposalState", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Pending" + }, + { + "name": "Passed" + }, + { + "name": "Failed" + } + ] + } + } + ], + "errors": [ + { + "code": 6000, + "name": "InvalidMarket", + "msg": "Either the `pass_market` or the `fail_market`'s tokens doesn't match the vaults supplied" + }, + { + "code": 6001, + "name": "TWAPMarketTooOld", + "msg": "`TWAPMarket` must have an `initial_slot` within 50 slots of the proposal's `slot_enqueued`" + }, + { + "code": 6002, + "name": "TWAPMarketInvalidExpectedValue", + "msg": "`TWAPMarket` must have an expected value of 1000, or 0.1 USDC per META" + }, + { + "code": 6003, + "name": "InvalidSettlementAuthority", + "msg": "One of the vaults has an invalid `settlement_authority`" + }, + { + "code": 6004, + "name": "ProposalTooYoung", + "msg": "Proposal is too young to be executed or rejected" + }, + { + "code": 6005, + "name": "MarketsTooYoung", + "msg": "Markets too young for proposal to be finalized" + }, + { + "code": 6006, + "name": "ProposalCannotPass", + "msg": "The market dictates that this proposal cannot pass" + }, + { + "code": 6007, + "name": "ProposalAlreadyFinalized", + "msg": "This proposal has already been finalized" + }, + { + "code": 6008, + "name": "InvalidVaultNonce", + "msg": "A conditional vault has an invalid nonce. A nonce should encode pass = 0 / fail = 1 in its most significant bit, base = 0 / quote = 1 in its second most significant bit, and the proposal number in least significant 32 bits" + } + ], + "metadata": { + "address": "meta3cxKzFBmWYgCVozmvCQAS3y9b3fGxrG9HkHL7Wi" + } +} \ No newline at end of file diff --git a/packages/futarchy-ts/lib/idl/autocrat_v0.ts b/packages/futarchy-ts/lib/idl/autocrat_v0.ts new file mode 100644 index 00000000..d646ed91 --- /dev/null +++ b/packages/futarchy-ts/lib/idl/autocrat_v0.ts @@ -0,0 +1,869 @@ +export type AutocratV0 = { + version: '0.1.0'; + name: 'autocrat_v0'; + instructions: [ + { + name: 'initializeDao'; + accounts: [ + { + name: 'dao'; + isMut: true; + isSigner: false; + }, + { + name: 'payer'; + isMut: true; + isSigner: true; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'metaMint'; + isMut: false; + isSigner: false; + }, + { + name: 'usdcMint'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'initializeProposal'; + accounts: [ + { + name: 'proposal'; + isMut: true; + isSigner: true; + }, + { + name: 'dao'; + isMut: true; + isSigner: false; + }, + { + name: 'daoTreasury'; + isMut: true; + isSigner: false; + }, + { + name: 'quoteVault'; + isMut: false; + isSigner: false; + }, + { + name: 'baseVault'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookPassMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookFailMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookTwapPassMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookTwapFailMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'proposer'; + isMut: true; + isSigner: true; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'descriptionUrl'; + type: 'string'; + }, + { + name: 'instruction'; + type: { + defined: 'ProposalInstruction'; + }; + }, + ]; + }, + { + name: 'finalizeProposal'; + accounts: [ + { + name: 'proposal'; + isMut: true; + isSigner: false; + }, + { + name: 'openbookTwapPassMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookTwapFailMarket'; + isMut: false; + isSigner: false; + }, + { + name: 'dao'; + isMut: false; + isSigner: false; + }, + { + name: 'baseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'quoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'vaultProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'daoTreasury'; + isMut: true; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'setPassThresholdBps'; + accounts: [ + { + name: 'dao'; + isMut: true; + isSigner: false; + }, + { + name: 'daoTreasury'; + isMut: false; + isSigner: true; + }, + ]; + args: [ + { + name: 'passThresholdBps'; + type: 'u16'; + }, + ]; + }, + { + name: 'setLastProposalSlot'; + accounts: [ + { + name: 'dao'; + isMut: true; + isSigner: false; + }, + { + name: 'daoTreasury'; + isMut: false; + isSigner: true; + }, + ]; + args: [ + { + name: 'lastProposalSlot'; + type: 'u64'; + }, + ]; + }, + { + name: 'setBaseBurnLamports'; + accounts: [ + { + name: 'dao'; + isMut: true; + isSigner: false; + }, + { + name: 'daoTreasury'; + isMut: false; + isSigner: true; + }, + ]; + args: [ + { + name: 'baseBurnLamports'; + type: 'u64'; + }, + ]; + }, + ]; + accounts: [ + { + name: 'dao'; + type: { + kind: 'struct'; + fields: [ + { + name: 'metaMint'; + type: 'publicKey'; + }, + { + name: 'usdcMint'; + type: 'publicKey'; + }, + { + name: 'passThresholdBps'; + type: 'u16'; + }, + { + name: 'proposalCount'; + type: 'u32'; + }, + { + name: 'lastProposalSlot'; + type: 'u64'; + }, + { + name: 'baseBurnLamports'; + type: 'u64'; + }, + { + name: 'burnDecayPerSlotLamports'; + type: 'u64'; + }, + { + name: 'treasuryPdaBump'; + type: 'u8'; + }, + { + name: 'treasury'; + type: 'publicKey'; + }, + ]; + }; + }, + { + name: 'proposal'; + type: { + kind: 'struct'; + fields: [ + { + name: 'number'; + type: 'u32'; + }, + { + name: 'proposer'; + type: 'publicKey'; + }, + { + name: 'descriptionUrl'; + type: 'string'; + }, + { + name: 'slotEnqueued'; + type: 'u64'; + }, + { + name: 'state'; + type: { + defined: 'ProposalState'; + }; + }, + { + name: 'instruction'; + type: { + defined: 'ProposalInstruction'; + }; + }, + { + name: 'openbookTwapPassMarket'; + type: 'publicKey'; + }, + { + name: 'openbookTwapFailMarket'; + type: 'publicKey'; + }, + { + name: 'openbookPassMarket'; + type: 'publicKey'; + }, + { + name: 'openbookFailMarket'; + type: 'publicKey'; + }, + { + name: 'baseVault'; + type: 'publicKey'; + }, + { + name: 'quoteVault'; + type: 'publicKey'; + }, + ]; + }; + }, + ]; + types: [ + { + name: 'ProposalInstruction'; + type: { + kind: 'struct'; + fields: [ + { + name: 'programId'; + type: 'publicKey'; + }, + { + name: 'accounts'; + type: { + vec: { + defined: 'ProposalAccount'; + }; + }; + }, + { + name: 'data'; + type: 'bytes'; + }, + ]; + }; + }, + { + name: 'ProposalAccount'; + type: { + kind: 'struct'; + fields: [ + { + name: 'pubkey'; + type: 'publicKey'; + }, + { + name: 'isSigner'; + type: 'bool'; + }, + { + name: 'isWritable'; + type: 'bool'; + }, + ]; + }; + }, + { + name: 'ProposalState'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Pending'; + }, + { + name: 'Passed'; + }, + { + name: 'Failed'; + }, + ]; + }; + }, + ]; + errors: [ + { + code: 6000; + name: 'InvalidMarket'; + msg: "Either the `pass_market` or the `fail_market`'s tokens doesn't match the vaults supplied"; + }, + { + code: 6001; + name: 'TWAPMarketTooOld'; + msg: "`TWAPMarket` must have an `initial_slot` within 50 slots of the proposal's `slot_enqueued`"; + }, + { + code: 6002; + name: 'TWAPMarketInvalidExpectedValue'; + msg: '`TWAPMarket` must have an expected value of 1000, or 0.1 USDC per META'; + }, + { + code: 6003; + name: 'InvalidSettlementAuthority'; + msg: 'One of the vaults has an invalid `settlement_authority`'; + }, + { + code: 6004; + name: 'ProposalTooYoung'; + msg: 'Proposal is too young to be executed or rejected'; + }, + { + code: 6005; + name: 'MarketsTooYoung'; + msg: 'Markets too young for proposal to be finalized'; + }, + { + code: 6006; + name: 'ProposalCannotPass'; + msg: 'The market dictates that this proposal cannot pass'; + }, + { + code: 6007; + name: 'ProposalAlreadyFinalized'; + msg: 'This proposal has already been finalized'; + }, + { + code: 6008; + name: 'InvalidVaultNonce'; + msg: 'A conditional vault has an invalid nonce. A nonce should encode pass = 0 / fail = 1 in its most significant bit, base = 0 / quote = 1 in its second most significant bit, and the proposal number in least significant 32 bits'; + }, + ]; +}; + +export const IDL: AutocratV0 = { + version: '0.1.0', + name: 'autocrat_v0', + instructions: [ + { + name: 'initializeDao', + accounts: [ + { + name: 'dao', + isMut: true, + isSigner: false, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + { + name: 'metaMint', + isMut: false, + isSigner: false, + }, + { + name: 'usdcMint', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'initializeProposal', + accounts: [ + { + name: 'proposal', + isMut: true, + isSigner: true, + }, + { + name: 'dao', + isMut: true, + isSigner: false, + }, + { + name: 'daoTreasury', + isMut: true, + isSigner: false, + }, + { + name: 'quoteVault', + isMut: false, + isSigner: false, + }, + { + name: 'baseVault', + isMut: false, + isSigner: false, + }, + { + name: 'openbookPassMarket', + isMut: false, + isSigner: false, + }, + { + name: 'openbookFailMarket', + isMut: false, + isSigner: false, + }, + { + name: 'openbookTwapPassMarket', + isMut: false, + isSigner: false, + }, + { + name: 'openbookTwapFailMarket', + isMut: false, + isSigner: false, + }, + { + name: 'proposer', + isMut: true, + isSigner: true, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'descriptionUrl', + type: 'string', + }, + { + name: 'instruction', + type: { + defined: 'ProposalInstruction', + }, + }, + ], + }, + { + name: 'finalizeProposal', + accounts: [ + { + name: 'proposal', + isMut: true, + isSigner: false, + }, + { + name: 'openbookTwapPassMarket', + isMut: false, + isSigner: false, + }, + { + name: 'openbookTwapFailMarket', + isMut: false, + isSigner: false, + }, + { + name: 'dao', + isMut: false, + isSigner: false, + }, + { + name: 'baseVault', + isMut: true, + isSigner: false, + }, + { + name: 'quoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'vaultProgram', + isMut: false, + isSigner: false, + }, + { + name: 'daoTreasury', + isMut: true, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'setPassThresholdBps', + accounts: [ + { + name: 'dao', + isMut: true, + isSigner: false, + }, + { + name: 'daoTreasury', + isMut: false, + isSigner: true, + }, + ], + args: [ + { + name: 'passThresholdBps', + type: 'u16', + }, + ], + }, + { + name: 'setLastProposalSlot', + accounts: [ + { + name: 'dao', + isMut: true, + isSigner: false, + }, + { + name: 'daoTreasury', + isMut: false, + isSigner: true, + }, + ], + args: [ + { + name: 'lastProposalSlot', + type: 'u64', + }, + ], + }, + { + name: 'setBaseBurnLamports', + accounts: [ + { + name: 'dao', + isMut: true, + isSigner: false, + }, + { + name: 'daoTreasury', + isMut: false, + isSigner: true, + }, + ], + args: [ + { + name: 'baseBurnLamports', + type: 'u64', + }, + ], + }, + ], + accounts: [ + { + name: 'dao', + type: { + kind: 'struct', + fields: [ + { + name: 'metaMint', + type: 'publicKey', + }, + { + name: 'usdcMint', + type: 'publicKey', + }, + { + name: 'passThresholdBps', + type: 'u16', + }, + { + name: 'proposalCount', + type: 'u32', + }, + { + name: 'lastProposalSlot', + type: 'u64', + }, + { + name: 'baseBurnLamports', + type: 'u64', + }, + { + name: 'burnDecayPerSlotLamports', + type: 'u64', + }, + { + name: 'treasuryPdaBump', + type: 'u8', + }, + { + name: 'treasury', + type: 'publicKey', + }, + ], + }, + }, + { + name: 'proposal', + type: { + kind: 'struct', + fields: [ + { + name: 'number', + type: 'u32', + }, + { + name: 'proposer', + type: 'publicKey', + }, + { + name: 'descriptionUrl', + type: 'string', + }, + { + name: 'slotEnqueued', + type: 'u64', + }, + { + name: 'state', + type: { + defined: 'ProposalState', + }, + }, + { + name: 'instruction', + type: { + defined: 'ProposalInstruction', + }, + }, + { + name: 'openbookTwapPassMarket', + type: 'publicKey', + }, + { + name: 'openbookTwapFailMarket', + type: 'publicKey', + }, + { + name: 'openbookPassMarket', + type: 'publicKey', + }, + { + name: 'openbookFailMarket', + type: 'publicKey', + }, + { + name: 'baseVault', + type: 'publicKey', + }, + { + name: 'quoteVault', + type: 'publicKey', + }, + ], + }, + }, + ], + types: [ + { + name: 'ProposalInstruction', + type: { + kind: 'struct', + fields: [ + { + name: 'programId', + type: 'publicKey', + }, + { + name: 'accounts', + type: { + vec: { + defined: 'ProposalAccount', + }, + }, + }, + { + name: 'data', + type: 'bytes', + }, + ], + }, + }, + { + name: 'ProposalAccount', + type: { + kind: 'struct', + fields: [ + { + name: 'pubkey', + type: 'publicKey', + }, + { + name: 'isSigner', + type: 'bool', + }, + { + name: 'isWritable', + type: 'bool', + }, + ], + }, + }, + { + name: 'ProposalState', + type: { + kind: 'enum', + variants: [ + { + name: 'Pending', + }, + { + name: 'Passed', + }, + { + name: 'Failed', + }, + ], + }, + }, + ], + errors: [ + { + code: 6000, + name: 'InvalidMarket', + msg: "Either the `pass_market` or the `fail_market`'s tokens doesn't match the vaults supplied", + }, + { + code: 6001, + name: 'TWAPMarketTooOld', + msg: "`TWAPMarket` must have an `initial_slot` within 50 slots of the proposal's `slot_enqueued`", + }, + { + code: 6002, + name: 'TWAPMarketInvalidExpectedValue', + msg: '`TWAPMarket` must have an expected value of 1000, or 0.1 USDC per META', + }, + { + code: 6003, + name: 'InvalidSettlementAuthority', + msg: 'One of the vaults has an invalid `settlement_authority`', + }, + { + code: 6004, + name: 'ProposalTooYoung', + msg: 'Proposal is too young to be executed or rejected', + }, + { + code: 6005, + name: 'MarketsTooYoung', + msg: 'Markets too young for proposal to be finalized', + }, + { + code: 6006, + name: 'ProposalCannotPass', + msg: 'The market dictates that this proposal cannot pass', + }, + { + code: 6007, + name: 'ProposalAlreadyFinalized', + msg: 'This proposal has already been finalized', + }, + { + code: 6008, + name: 'InvalidVaultNonce', + msg: 'A conditional vault has an invalid nonce. A nonce should encode pass = 0 / fail = 1 in its most significant bit, base = 0 / quote = 1 in its second most significant bit, and the proposal number in least significant 32 bits', + }, + ], +}; diff --git a/packages/futarchy-ts/lib/idl/conditional_vault.json b/packages/futarchy-ts/lib/idl/conditional_vault.json new file mode 100644 index 00000000..e1fedbac --- /dev/null +++ b/packages/futarchy-ts/lib/idl/conditional_vault.json @@ -0,0 +1,304 @@ +{ + "version": "0.1.0", + "name": "conditional_vault", + "instructions": [ + { + "name": "initializeConditionalVault", + "accounts": [ + { + "name": "vault", + "isMut": true, + "isSigner": false + }, + { + "name": "underlyingTokenMint", + "isMut": false, + "isSigner": false + }, + { + "name": "conditionalOnFinalizeTokenMint", + "isMut": true, + "isSigner": true + }, + { + "name": "conditionalOnRevertTokenMint", + "isMut": true, + "isSigner": true + }, + { + "name": "vaultUnderlyingTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "associatedTokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "settlementAuthority", + "type": "publicKey" + }, + { + "name": "nonce", + "type": "u64" + } + ] + }, + { + "name": "settleConditionalVault", + "accounts": [ + { + "name": "settlementAuthority", + "isMut": false, + "isSigner": true + }, + { + "name": "vault", + "isMut": true, + "isSigner": false + } + ], + "args": [ + { + "name": "newStatus", + "type": { + "defined": "VaultStatus" + } + } + ] + }, + { + "name": "mintConditionalTokens", + "accounts": [ + { + "name": "vault", + "isMut": false, + "isSigner": false + }, + { + "name": "conditionalOnFinalizeTokenMint", + "isMut": true, + "isSigner": false + }, + { + "name": "conditionalOnRevertTokenMint", + "isMut": true, + "isSigner": false + }, + { + "name": "vaultUnderlyingTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "userUnderlyingTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "userConditionalOnFinalizeTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "userConditionalOnRevertTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "redeemConditionalTokensForUnderlyingTokens", + "accounts": [ + { + "name": "vault", + "isMut": false, + "isSigner": false + }, + { + "name": "conditionalOnFinalizeTokenMint", + "isMut": true, + "isSigner": false + }, + { + "name": "conditionalOnRevertTokenMint", + "isMut": true, + "isSigner": false + }, + { + "name": "vaultUnderlyingTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "authority", + "isMut": false, + "isSigner": true + }, + { + "name": "userConditionalOnFinalizeTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "userConditionalOnRevertTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "userUnderlyingTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [] + } + ], + "accounts": [ + { + "name": "ConditionalVault", + "type": { + "kind": "struct", + "fields": [ + { + "name": "status", + "type": { + "defined": "VaultStatus" + } + }, + { + "name": "settlementAuthority", + "docs": [ + "The account that can either finalize the vault to make conditional tokens", + "redeemable for underlying tokens or revert the vault to make deposit", + "slips redeemable for underlying tokens." + ], + "type": "publicKey" + }, + { + "name": "underlyingTokenMint", + "docs": [ + "The mint of the tokens that are deposited into the vault." + ], + "type": "publicKey" + }, + { + "name": "nonce", + "docs": [ + "A nonce to allow a single account to be the settlement authority of multiple", + "vaults with the same underlying token mints." + ], + "type": "u64" + }, + { + "name": "underlyingTokenAccount", + "docs": [ + "The vault's storage account for deposited funds." + ], + "type": "publicKey" + }, + { + "name": "conditionalOnFinalizeTokenMint", + "type": "publicKey" + }, + { + "name": "conditionalOnRevertTokenMint", + "type": "publicKey" + }, + { + "name": "pdaBump", + "type": "u8" + } + ] + } + } + ], + "types": [ + { + "name": "VaultStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Active" + }, + { + "name": "Finalized" + }, + { + "name": "Reverted" + } + ] + } + } + ], + "errors": [ + { + "code": 6000, + "name": "InsufficientUnderlyingTokens", + "msg": "Insufficient underlying token balance to mint this amount of conditional tokens" + }, + { + "code": 6001, + "name": "InvalidVaultUnderlyingTokenAccount", + "msg": "This `vault_underlying_token_account` is not this vault's `underlying_token_account`" + }, + { + "code": 6002, + "name": "InvalidConditionalTokenMint", + "msg": "This conditional token mint is not this vault's conditional token mint" + }, + { + "code": 6003, + "name": "CantRedeemConditionalTokens", + "msg": "Vault needs to be settled as finalized before users can redeem conditional tokens for underlying tokens" + }, + { + "code": 6004, + "name": "VaultAlreadySettled", + "msg": "Once a vault has been settled, its status as either finalized or reverted cannot be changed" + } + ], + "metadata": { + "address": "vaU1tVLj8RFk7mNj1BxqgAsMKKaL8UvEUHvU3tdbZPe" + } +} \ No newline at end of file diff --git a/packages/futarchy-ts/lib/idl/conditional_vault.ts b/packages/futarchy-ts/lib/idl/conditional_vault.ts new file mode 100644 index 00000000..3d2627d4 --- /dev/null +++ b/packages/futarchy-ts/lib/idl/conditional_vault.ts @@ -0,0 +1,595 @@ +export type ConditionalVault = { + version: '0.1.0'; + name: 'conditional_vault'; + instructions: [ + { + name: 'initializeConditionalVault'; + accounts: [ + { + name: 'vault'; + isMut: true; + isSigner: false; + }, + { + name: 'underlyingTokenMint'; + isMut: false; + isSigner: false; + }, + { + name: 'conditionalOnFinalizeTokenMint'; + isMut: true; + isSigner: true; + }, + { + name: 'conditionalOnRevertTokenMint'; + isMut: true; + isSigner: true; + }, + { + name: 'vaultUnderlyingTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'payer'; + isMut: true; + isSigner: true; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'associatedTokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'settlementAuthority'; + type: 'publicKey'; + }, + { + name: 'nonce'; + type: 'u64'; + }, + ]; + }, + { + name: 'settleConditionalVault'; + accounts: [ + { + name: 'settlementAuthority'; + isMut: false; + isSigner: true; + }, + { + name: 'vault'; + isMut: true; + isSigner: false; + }, + ]; + args: [ + { + name: 'newStatus'; + type: { + defined: 'VaultStatus'; + }; + }, + ]; + }, + { + name: 'mintConditionalTokens'; + accounts: [ + { + name: 'vault'; + isMut: false; + isSigner: false; + }, + { + name: 'conditionalOnFinalizeTokenMint'; + isMut: true; + isSigner: false; + }, + { + name: 'conditionalOnRevertTokenMint'; + isMut: true; + isSigner: false; + }, + { + name: 'vaultUnderlyingTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'authority'; + isMut: false; + isSigner: true; + }, + { + name: 'userUnderlyingTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userConditionalOnFinalizeTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userConditionalOnRevertTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'amount'; + type: 'u64'; + }, + ]; + }, + { + name: 'redeemConditionalTokensForUnderlyingTokens'; + accounts: [ + { + name: 'vault'; + isMut: false; + isSigner: false; + }, + { + name: 'conditionalOnFinalizeTokenMint'; + isMut: true; + isSigner: false; + }, + { + name: 'conditionalOnRevertTokenMint'; + isMut: true; + isSigner: false; + }, + { + name: 'vaultUnderlyingTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'authority'; + isMut: false; + isSigner: true; + }, + { + name: 'userConditionalOnFinalizeTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userConditionalOnRevertTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userUnderlyingTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + ]; + accounts: [ + { + name: 'conditionalVault'; + type: { + kind: 'struct'; + fields: [ + { + name: 'status'; + type: { + defined: 'VaultStatus'; + }; + }, + { + name: 'settlementAuthority'; + docs: [ + 'The account that can either finalize the vault to make conditional tokens', + 'redeemable for underlying tokens or revert the vault to make deposit', + 'slips redeemable for underlying tokens.', + ]; + type: 'publicKey'; + }, + { + name: 'underlyingTokenMint'; + docs: ['The mint of the tokens that are deposited into the vault.']; + type: 'publicKey'; + }, + { + name: 'nonce'; + docs: [ + 'A nonce to allow a single account to be the settlement authority of multiple', + 'vaults with the same underlying token mints.', + ]; + type: 'u64'; + }, + { + name: 'underlyingTokenAccount'; + docs: ["The vault's storage account for deposited funds."]; + type: 'publicKey'; + }, + { + name: 'conditionalOnFinalizeTokenMint'; + type: 'publicKey'; + }, + { + name: 'conditionalOnRevertTokenMint'; + type: 'publicKey'; + }, + { + name: 'pdaBump'; + type: 'u8'; + }, + ]; + }; + }, + ]; + types: [ + { + name: 'VaultStatus'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Active'; + }, + { + name: 'Finalized'; + }, + { + name: 'Reverted'; + }, + ]; + }; + }, + ]; + errors: [ + { + code: 6000; + name: 'InsufficientUnderlyingTokens'; + msg: 'Insufficient underlying token balance to mint this amount of conditional tokens'; + }, + { + code: 6001; + name: 'InvalidVaultUnderlyingTokenAccount'; + msg: "This `vault_underlying_token_account` is not this vault's `underlying_token_account`"; + }, + { + code: 6002; + name: 'InvalidConditionalTokenMint'; + msg: "This conditional token mint is not this vault's conditional token mint"; + }, + { + code: 6003; + name: 'CantRedeemConditionalTokens'; + msg: 'Vault needs to be settled as finalized before users can redeem conditional tokens for underlying tokens'; + }, + { + code: 6004; + name: 'VaultAlreadySettled'; + msg: 'Once a vault has been settled, its status as either finalized or reverted cannot be changed'; + }, + ]; +}; + +export const IDL: ConditionalVault = { + version: '0.1.0', + name: 'conditional_vault', + instructions: [ + { + name: 'initializeConditionalVault', + accounts: [ + { + name: 'vault', + isMut: true, + isSigner: false, + }, + { + name: 'underlyingTokenMint', + isMut: false, + isSigner: false, + }, + { + name: 'conditionalOnFinalizeTokenMint', + isMut: true, + isSigner: true, + }, + { + name: 'conditionalOnRevertTokenMint', + isMut: true, + isSigner: true, + }, + { + name: 'vaultUnderlyingTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'associatedTokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'settlementAuthority', + type: 'publicKey', + }, + { + name: 'nonce', + type: 'u64', + }, + ], + }, + { + name: 'settleConditionalVault', + accounts: [ + { + name: 'settlementAuthority', + isMut: false, + isSigner: true, + }, + { + name: 'vault', + isMut: true, + isSigner: false, + }, + ], + args: [ + { + name: 'newStatus', + type: { + defined: 'VaultStatus', + }, + }, + ], + }, + { + name: 'mintConditionalTokens', + accounts: [ + { + name: 'vault', + isMut: false, + isSigner: false, + }, + { + name: 'conditionalOnFinalizeTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'conditionalOnRevertTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'vaultUnderlyingTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'authority', + isMut: false, + isSigner: true, + }, + { + name: 'userUnderlyingTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userConditionalOnFinalizeTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userConditionalOnRevertTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'amount', + type: 'u64', + }, + ], + }, + { + name: 'redeemConditionalTokensForUnderlyingTokens', + accounts: [ + { + name: 'vault', + isMut: false, + isSigner: false, + }, + { + name: 'conditionalOnFinalizeTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'conditionalOnRevertTokenMint', + isMut: true, + isSigner: false, + }, + { + name: 'vaultUnderlyingTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'authority', + isMut: false, + isSigner: true, + }, + { + name: 'userConditionalOnFinalizeTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userConditionalOnRevertTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userUnderlyingTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + ], + accounts: [ + { + name: 'conditionalVault', + type: { + kind: 'struct', + fields: [ + { + name: 'status', + type: { + defined: 'VaultStatus', + }, + }, + { + name: 'settlementAuthority', + docs: [ + 'The account that can either finalize the vault to make conditional tokens', + 'redeemable for underlying tokens or revert the vault to make deposit', + 'slips redeemable for underlying tokens.', + ], + type: 'publicKey', + }, + { + name: 'underlyingTokenMint', + docs: ['The mint of the tokens that are deposited into the vault.'], + type: 'publicKey', + }, + { + name: 'nonce', + docs: [ + 'A nonce to allow a single account to be the settlement authority of multiple', + 'vaults with the same underlying token mints.', + ], + type: 'u64', + }, + { + name: 'underlyingTokenAccount', + docs: ["The vault's storage account for deposited funds."], + type: 'publicKey', + }, + { + name: 'conditionalOnFinalizeTokenMint', + type: 'publicKey', + }, + { + name: 'conditionalOnRevertTokenMint', + type: 'publicKey', + }, + { + name: 'pdaBump', + type: 'u8', + }, + ], + }, + }, + ], + types: [ + { + name: 'VaultStatus', + type: { + kind: 'enum', + variants: [ + { + name: 'Active', + }, + { + name: 'Finalized', + }, + { + name: 'Reverted', + }, + ], + }, + }, + ], + errors: [ + { + code: 6000, + name: 'InsufficientUnderlyingTokens', + msg: 'Insufficient underlying token balance to mint this amount of conditional tokens', + }, + { + code: 6001, + name: 'InvalidVaultUnderlyingTokenAccount', + msg: "This `vault_underlying_token_account` is not this vault's `underlying_token_account`", + }, + { + code: 6002, + name: 'InvalidConditionalTokenMint', + msg: "This conditional token mint is not this vault's conditional token mint", + }, + { + code: 6003, + name: 'CantRedeemConditionalTokens', + msg: 'Vault needs to be settled as finalized before users can redeem conditional tokens for underlying tokens', + }, + { + code: 6004, + name: 'VaultAlreadySettled', + msg: 'Once a vault has been settled, its status as either finalized or reverted cannot be changed', + }, + ], +}; diff --git a/packages/futarchy-ts/lib/idl/openbook_twap.json b/packages/futarchy-ts/lib/idl/openbook_twap.json new file mode 100644 index 00000000..08ab14ea --- /dev/null +++ b/packages/futarchy-ts/lib/idl/openbook_twap.json @@ -0,0 +1,730 @@ +{ + "version": "1.0.0", + "name": "openbook_twap", + "instructions": [ + { + "name": "createTwapMarket", + "docs": [ + "`expected_value` will be the first observation of the TWAP, which is", + "necessary for anti-manipulation" + ], + "accounts": [ + { + "name": "market", + "isMut": false, + "isSigner": false + }, + { + "name": "twapMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "payer", + "isMut": true, + "isSigner": true + } + ], + "args": [ + { + "name": "expectedValue", + "type": "u64" + } + ] + }, + { + "name": "placeOrder", + "accounts": [ + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "openOrdersAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "twapMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "market", + "isMut": true, + "isSigner": false + }, + { + "name": "bids", + "isMut": true, + "isSigner": false + }, + { + "name": "asks", + "isMut": true, + "isSigner": false + }, + { + "name": "eventHeap", + "isMut": true, + "isSigner": false + }, + { + "name": "marketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "placeOrderArgs", + "type": { + "defined": "PlaceOrderArgs" + } + } + ], + "returns": { + "option": "u128" + } + }, + { + "name": "editOrder", + "accounts": [ + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "openOrdersAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "twapMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "userTokenAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "market", + "isMut": true, + "isSigner": false + }, + { + "name": "bids", + "isMut": true, + "isSigner": false + }, + { + "name": "asks", + "isMut": true, + "isSigner": false + }, + { + "name": "eventHeap", + "isMut": true, + "isSigner": false + }, + { + "name": "marketVault", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "clientOrderId", + "type": "u64" + }, + { + "name": "expectedCancelSize", + "type": "i64" + }, + { + "name": "placeOrder", + "type": { + "defined": "PlaceOrderArgs" + } + } + ], + "returns": { + "option": "u128" + } + }, + { + "name": "cancelOrderByClientId", + "accounts": [ + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "twapMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "openOrdersAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "market", + "isMut": false, + "isSigner": false + }, + { + "name": "bids", + "isMut": true, + "isSigner": false + }, + { + "name": "asks", + "isMut": true, + "isSigner": false + }, + { + "name": "openbookProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "clientOrderId", + "type": "u64" + } + ], + "returns": "i64" + }, + { + "name": "cancelAllOrders", + "accounts": [ + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "twapMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "openOrdersAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "market", + "isMut": false, + "isSigner": false + }, + { + "name": "bids", + "isMut": true, + "isSigner": false + }, + { + "name": "asks", + "isMut": true, + "isSigner": false + }, + { + "name": "openbookProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "sideOption", + "type": { + "option": { + "defined": "Side" + } + } + }, + { + "name": "limit", + "type": "u8" + } + ] + }, + { + "name": "placeTakeOrder", + "accounts": [ + { + "name": "twapMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "signer", + "isMut": true, + "isSigner": true + }, + { + "name": "market", + "isMut": true, + "isSigner": false + }, + { + "name": "marketAuthority", + "isMut": false, + "isSigner": false + }, + { + "name": "bids", + "isMut": true, + "isSigner": false + }, + { + "name": "asks", + "isMut": true, + "isSigner": false + }, + { + "name": "marketBaseVault", + "isMut": true, + "isSigner": false + }, + { + "name": "marketQuoteVault", + "isMut": true, + "isSigner": false + }, + { + "name": "eventHeap", + "isMut": true, + "isSigner": false + }, + { + "name": "userBaseAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "userQuoteAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "args", + "type": { + "defined": "PlaceTakeOrderArgs" + } + } + ] + }, + { + "name": "cancelAndPlaceOrders", + "accounts": [ + { + "name": "signer", + "isMut": false, + "isSigner": true + }, + { + "name": "twapMarket", + "isMut": true, + "isSigner": false + }, + { + "name": "openOrdersAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "userQuoteAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "userBaseAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "market", + "isMut": true, + "isSigner": false + }, + { + "name": "bids", + "isMut": true, + "isSigner": false + }, + { + "name": "asks", + "isMut": true, + "isSigner": false + }, + { + "name": "eventHeap", + "isMut": true, + "isSigner": false + }, + { + "name": "marketQuoteVault", + "isMut": true, + "isSigner": false + }, + { + "name": "marketBaseVault", + "isMut": true, + "isSigner": false + }, + { + "name": "tokenProgram", + "isMut": false, + "isSigner": false + }, + { + "name": "openbookProgram", + "isMut": false, + "isSigner": false + } + ], + "args": [ + { + "name": "cancelClientOrdersIds", + "type": { + "vec": "u64" + } + }, + { + "name": "placeOrders", + "type": { + "vec": { + "defined": "PlaceOrderArgs" + } + } + } + ], + "returns": { + "vec": { + "option": "u128" + } + } + }, + { + "name": "getBestBidAndAsk", + "accounts": [ + { + "name": "market", + "isMut": false, + "isSigner": false + }, + { + "name": "bids", + "isMut": false, + "isSigner": false + }, + { + "name": "asks", + "isMut": false, + "isSigner": false + } + ], + "args": [], + "returns": { + "vec": "u64" + } + } + ], + "accounts": [ + { + "name": "TWAPMarket", + "type": { + "kind": "struct", + "fields": [ + { + "name": "market", + "type": "publicKey" + }, + { + "name": "pdaBump", + "type": "u8" + }, + { + "name": "twapOracle", + "type": { + "defined": "TWAPOracle" + } + } + ] + } + } + ], + "types": [ + { + "name": "TWAPOracle", + "type": { + "kind": "struct", + "fields": [ + { + "name": "expectedValue", + "type": "u64" + }, + { + "name": "initialSlot", + "type": "u64" + }, + { + "name": "lastUpdatedSlot", + "type": "u64" + }, + { + "name": "lastObservedSlot", + "type": "u64" + }, + { + "name": "lastObservation", + "type": "u64" + }, + { + "name": "observationAggregator", + "type": "u128" + } + ] + } + }, + { + "name": "PlaceOrderArgs", + "type": { + "kind": "struct", + "fields": [ + { + "name": "side", + "type": { + "defined": "Side" + } + }, + { + "name": "priceLots", + "type": "i64" + }, + { + "name": "maxBaseLots", + "type": "i64" + }, + { + "name": "maxQuoteLotsIncludingFees", + "type": "i64" + }, + { + "name": "clientOrderId", + "type": "u64" + }, + { + "name": "orderType", + "type": { + "defined": "PlaceOrderType" + } + }, + { + "name": "expiryTimestamp", + "type": "u64" + }, + { + "name": "selfTradeBehavior", + "type": { + "defined": "SelfTradeBehavior" + } + }, + { + "name": "limit", + "type": "u8" + } + ] + } + }, + { + "name": "PlaceTakeOrderArgs", + "type": { + "kind": "struct", + "fields": [ + { + "name": "side", + "type": { + "defined": "Side" + } + }, + { + "name": "priceLots", + "type": "i64" + }, + { + "name": "maxBaseLots", + "type": "i64" + }, + { + "name": "maxQuoteLotsIncludingFees", + "type": "i64" + }, + { + "name": "orderType", + "type": { + "defined": "PlaceOrderType" + } + }, + { + "name": "limit", + "type": "u8" + } + ] + } + }, + { + "name": "SelfTradeBehavior", + "type": { + "kind": "enum", + "variants": [ + { + "name": "DecrementTake" + }, + { + "name": "CancelProvide" + }, + { + "name": "AbortTransaction" + } + ] + } + }, + { + "name": "PlaceOrderType", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Limit" + }, + { + "name": "ImmediateOrCancel" + }, + { + "name": "PostOnly" + }, + { + "name": "Market" + }, + { + "name": "PostOnlySlide" + } + ] + } + }, + { + "name": "Side", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Bid" + }, + { + "name": "Ask" + } + ] + } + } + ], + "errors": [ + { + "code": 6000, + "name": "InvalidOpenOrdersAdmin", + "msg": "The `open_orders_admin` of the underlying market must be equal to the `TWAPMarket` PDA" + }, + { + "code": 6001, + "name": "InvalidCloseMarketAdmin", + "msg": "The `close_market_admin` of the underlying market must be equal to the `TWAPMarket` PDA" + }, + { + "code": 6002, + "name": "NonZeroExpiry", + "msg": "Market must not expire (have `time_expiry` == 0)" + }, + { + "code": 6003, + "name": "NoOracles", + "msg": "Oracle-pegged trades mess up the TWAP so oracles and oracle-pegged trades aren't allowed" + }, + { + "code": 6004, + "name": "InvalidMakerFee", + "msg": "Maker fee must be zero" + }, + { + "code": 6005, + "name": "InvalidTakerFee", + "msg": "Taker fee must be zero" + }, + { + "code": 6006, + "name": "InvalidSeqNum", + "msg": "Seq num must be zero" + }, + { + "code": 6007, + "name": "InvalidConsumeEventsAdmin", + "msg": "Consume events admin must be None" + } + ] +} \ No newline at end of file diff --git a/packages/futarchy-ts/lib/idl/openbook_twap.ts b/packages/futarchy-ts/lib/idl/openbook_twap.ts new file mode 100644 index 00000000..40090a35 --- /dev/null +++ b/packages/futarchy-ts/lib/idl/openbook_twap.ts @@ -0,0 +1,1461 @@ +export type OpenbookTwap = { + version: '1.0.0'; + name: 'openbook_twap'; + instructions: [ + { + name: 'createTwapMarket'; + docs: [ + '`expected_value` will be the first observation of the TWAP, which is', + 'necessary for anti-manipulation', + ]; + accounts: [ + { + name: 'market'; + isMut: false; + isSigner: false; + }, + { + name: 'twapMarket'; + isMut: true; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'payer'; + isMut: true; + isSigner: true; + }, + ]; + args: [ + { + name: 'expectedValue'; + type: 'u64'; + }, + ]; + }, + { + name: 'placeOrder'; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'twapMarket'; + isMut: true; + isSigner: false; + }, + { + name: 'userTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'marketVault'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'placeOrderArgs'; + type: { + defined: 'PlaceOrderArgs'; + }; + }, + ]; + returns: { + option: 'u128'; + }; + }, + { + name: 'editOrder'; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'twapMarket'; + isMut: true; + isSigner: false; + }, + { + name: 'userTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'marketVault'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'clientOrderId'; + type: 'u64'; + }, + { + name: 'expectedCancelSize'; + type: 'i64'; + }, + { + name: 'placeOrder'; + type: { + defined: 'PlaceOrderArgs'; + }; + }, + ]; + returns: { + option: 'u128'; + }; + }, + { + name: 'cancelOrderByClientId'; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'twapMarket'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'openbookProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'clientOrderId'; + type: 'u64'; + }, + ]; + returns: 'i64'; + }, + { + name: 'cancelAllOrders'; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'twapMarket'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'openbookProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'sideOption'; + type: { + option: { + defined: 'Side'; + }; + }; + }, + { + name: 'limit'; + type: 'u8'; + }, + ]; + }, + { + name: 'placeTakeOrder'; + accounts: [ + { + name: 'twapMarket'; + isMut: true; + isSigner: false; + }, + { + name: 'signer'; + isMut: true; + isSigner: true; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'marketAuthority'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'marketBaseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'userBaseAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userQuoteAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'args'; + type: { + defined: 'PlaceTakeOrderArgs'; + }; + }, + ]; + }, + { + name: 'cancelAndPlaceOrders'; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'twapMarket'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userQuoteAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userBaseAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'marketBaseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'openbookProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'cancelClientOrdersIds'; + type: { + vec: 'u64'; + }; + }, + { + name: 'placeOrders'; + type: { + vec: { + defined: 'PlaceOrderArgs'; + }; + }; + }, + ]; + returns: { + vec: { + option: 'u128'; + }; + }; + }, + { + name: 'getBestBidAndAsk'; + accounts: [ + { + name: 'market'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: false; + isSigner: false; + }, + { + name: 'asks'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + returns: { + vec: 'u64'; + }; + }, + ]; + accounts: [ + { + name: 'twapMarket'; + type: { + kind: 'struct'; + fields: [ + { + name: 'market'; + type: 'publicKey'; + }, + { + name: 'pdaBump'; + type: 'u8'; + }, + { + name: 'twapOracle'; + type: { + defined: 'TWAPOracle'; + }; + }, + ]; + }; + }, + ]; + types: [ + { + name: 'TWAPOracle'; + type: { + kind: 'struct'; + fields: [ + { + name: 'expectedValue'; + type: 'u64'; + }, + { + name: 'initialSlot'; + type: 'u64'; + }, + { + name: 'lastUpdatedSlot'; + type: 'u64'; + }, + { + name: 'lastObservedSlot'; + type: 'u64'; + }, + { + name: 'lastObservation'; + type: 'u64'; + }, + { + name: 'observationAggregator'; + type: 'u128'; + }, + ]; + }; + }, + { + name: 'PlaceOrderArgs'; + type: { + kind: 'struct'; + fields: [ + { + name: 'side'; + type: { + defined: 'Side'; + }; + }, + { + name: 'priceLots'; + type: 'i64'; + }, + { + name: 'maxBaseLots'; + type: 'i64'; + }, + { + name: 'maxQuoteLotsIncludingFees'; + type: 'i64'; + }, + { + name: 'clientOrderId'; + type: 'u64'; + }, + { + name: 'orderType'; + type: { + defined: 'PlaceOrderType'; + }; + }, + { + name: 'expiryTimestamp'; + type: 'u64'; + }, + { + name: 'selfTradeBehavior'; + type: { + defined: 'SelfTradeBehavior'; + }; + }, + { + name: 'limit'; + type: 'u8'; + }, + ]; + }; + }, + { + name: 'PlaceTakeOrderArgs'; + type: { + kind: 'struct'; + fields: [ + { + name: 'side'; + type: { + defined: 'Side'; + }; + }, + { + name: 'priceLots'; + type: 'i64'; + }, + { + name: 'maxBaseLots'; + type: 'i64'; + }, + { + name: 'maxQuoteLotsIncludingFees'; + type: 'i64'; + }, + { + name: 'orderType'; + type: { + defined: 'PlaceOrderType'; + }; + }, + { + name: 'limit'; + type: 'u8'; + }, + ]; + }; + }, + { + name: 'SelfTradeBehavior'; + type: { + kind: 'enum'; + variants: [ + { + name: 'DecrementTake'; + }, + { + name: 'CancelProvide'; + }, + { + name: 'AbortTransaction'; + }, + ]; + }; + }, + { + name: 'PlaceOrderType'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Limit'; + }, + { + name: 'ImmediateOrCancel'; + }, + { + name: 'PostOnly'; + }, + { + name: 'Market'; + }, + { + name: 'PostOnlySlide'; + }, + ]; + }; + }, + { + name: 'Side'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Bid'; + }, + { + name: 'Ask'; + }, + ]; + }; + }, + ]; + errors: [ + { + code: 6000; + name: 'InvalidOpenOrdersAdmin'; + msg: 'The `open_orders_admin` of the underlying market must be equal to the `TWAPMarket` PDA'; + }, + { + code: 6001; + name: 'InvalidCloseMarketAdmin'; + msg: 'The `close_market_admin` of the underlying market must be equal to the `TWAPMarket` PDA'; + }, + { + code: 6002; + name: 'NonZeroExpiry'; + msg: 'Market must not expire (have `time_expiry` == 0)'; + }, + { + code: 6003; + name: 'NoOracles'; + msg: "Oracle-pegged trades mess up the TWAP so oracles and oracle-pegged trades aren't allowed"; + }, + { + code: 6004; + name: 'InvalidMakerFee'; + msg: 'Maker fee must be zero'; + }, + { + code: 6005; + name: 'InvalidTakerFee'; + msg: 'Taker fee must be zero'; + }, + { + code: 6006; + name: 'InvalidSeqNum'; + msg: 'Seq num must be zero'; + }, + { + code: 6007; + name: 'InvalidConsumeEventsAdmin'; + msg: 'Consume events admin must be None'; + }, + ]; +}; + +export const IDL: OpenbookTwap = { + version: '1.0.0', + name: 'openbook_twap', + instructions: [ + { + name: 'createTwapMarket', + docs: [ + '`expected_value` will be the first observation of the TWAP, which is', + 'necessary for anti-manipulation', + ], + accounts: [ + { + name: 'market', + isMut: false, + isSigner: false, + }, + { + name: 'twapMarket', + isMut: true, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + ], + args: [ + { + name: 'expectedValue', + type: 'u64', + }, + ], + }, + { + name: 'placeOrder', + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'twapMarket', + isMut: true, + isSigner: false, + }, + { + name: 'userTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'marketVault', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'openbookProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'placeOrderArgs', + type: { + defined: 'PlaceOrderArgs', + }, + }, + ], + returns: { + option: 'u128', + }, + }, + { + name: 'editOrder', + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'twapMarket', + isMut: true, + isSigner: false, + }, + { + name: 'userTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'marketVault', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'openbookProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'clientOrderId', + type: 'u64', + }, + { + name: 'expectedCancelSize', + type: 'i64', + }, + { + name: 'placeOrder', + type: { + defined: 'PlaceOrderArgs', + }, + }, + ], + returns: { + option: 'u128', + }, + }, + { + name: 'cancelOrderByClientId', + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'twapMarket', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'openbookProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'clientOrderId', + type: 'u64', + }, + ], + returns: 'i64', + }, + { + name: 'cancelAllOrders', + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'twapMarket', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'openbookProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'sideOption', + type: { + option: { + defined: 'Side', + }, + }, + }, + { + name: 'limit', + type: 'u8', + }, + ], + }, + { + name: 'placeTakeOrder', + accounts: [ + { + name: 'twapMarket', + isMut: true, + isSigner: false, + }, + { + name: 'signer', + isMut: true, + isSigner: true, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'marketAuthority', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'marketBaseVault', + isMut: true, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'userBaseAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userQuoteAccount', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'openbookProgram', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'args', + type: { + defined: 'PlaceTakeOrderArgs', + }, + }, + ], + }, + { + name: 'cancelAndPlaceOrders', + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'twapMarket', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userQuoteAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userBaseAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'marketBaseVault', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'openbookProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'cancelClientOrdersIds', + type: { + vec: 'u64', + }, + }, + { + name: 'placeOrders', + type: { + vec: { + defined: 'PlaceOrderArgs', + }, + }, + }, + ], + returns: { + vec: { + option: 'u128', + }, + }, + }, + { + name: 'getBestBidAndAsk', + accounts: [ + { + name: 'market', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: false, + isSigner: false, + }, + { + name: 'asks', + isMut: false, + isSigner: false, + }, + ], + args: [], + returns: { + vec: 'u64', + }, + }, + ], + accounts: [ + { + name: 'twapMarket', + type: { + kind: 'struct', + fields: [ + { + name: 'market', + type: 'publicKey', + }, + { + name: 'pdaBump', + type: 'u8', + }, + { + name: 'twapOracle', + type: { + defined: 'TWAPOracle', + }, + }, + ], + }, + }, + ], + types: [ + { + name: 'TWAPOracle', + type: { + kind: 'struct', + fields: [ + { + name: 'expectedValue', + type: 'u64', + }, + { + name: 'initialSlot', + type: 'u64', + }, + { + name: 'lastUpdatedSlot', + type: 'u64', + }, + { + name: 'lastObservedSlot', + type: 'u64', + }, + { + name: 'lastObservation', + type: 'u64', + }, + { + name: 'observationAggregator', + type: 'u128', + }, + ], + }, + }, + { + name: 'PlaceOrderArgs', + type: { + kind: 'struct', + fields: [ + { + name: 'side', + type: { + defined: 'Side', + }, + }, + { + name: 'priceLots', + type: 'i64', + }, + { + name: 'maxBaseLots', + type: 'i64', + }, + { + name: 'maxQuoteLotsIncludingFees', + type: 'i64', + }, + { + name: 'clientOrderId', + type: 'u64', + }, + { + name: 'orderType', + type: { + defined: 'PlaceOrderType', + }, + }, + { + name: 'expiryTimestamp', + type: 'u64', + }, + { + name: 'selfTradeBehavior', + type: { + defined: 'SelfTradeBehavior', + }, + }, + { + name: 'limit', + type: 'u8', + }, + ], + }, + }, + { + name: 'PlaceTakeOrderArgs', + type: { + kind: 'struct', + fields: [ + { + name: 'side', + type: { + defined: 'Side', + }, + }, + { + name: 'priceLots', + type: 'i64', + }, + { + name: 'maxBaseLots', + type: 'i64', + }, + { + name: 'maxQuoteLotsIncludingFees', + type: 'i64', + }, + { + name: 'orderType', + type: { + defined: 'PlaceOrderType', + }, + }, + { + name: 'limit', + type: 'u8', + }, + ], + }, + }, + { + name: 'SelfTradeBehavior', + type: { + kind: 'enum', + variants: [ + { + name: 'DecrementTake', + }, + { + name: 'CancelProvide', + }, + { + name: 'AbortTransaction', + }, + ], + }, + }, + { + name: 'PlaceOrderType', + type: { + kind: 'enum', + variants: [ + { + name: 'Limit', + }, + { + name: 'ImmediateOrCancel', + }, + { + name: 'PostOnly', + }, + { + name: 'Market', + }, + { + name: 'PostOnlySlide', + }, + ], + }, + }, + { + name: 'Side', + type: { + kind: 'enum', + variants: [ + { + name: 'Bid', + }, + { + name: 'Ask', + }, + ], + }, + }, + ], + errors: [ + { + code: 6000, + name: 'InvalidOpenOrdersAdmin', + msg: 'The `open_orders_admin` of the underlying market must be equal to the `TWAPMarket` PDA', + }, + { + code: 6001, + name: 'InvalidCloseMarketAdmin', + msg: 'The `close_market_admin` of the underlying market must be equal to the `TWAPMarket` PDA', + }, + { + code: 6002, + name: 'NonZeroExpiry', + msg: 'Market must not expire (have `time_expiry` == 0)', + }, + { + code: 6003, + name: 'NoOracles', + msg: "Oracle-pegged trades mess up the TWAP so oracles and oracle-pegged trades aren't allowed", + }, + { + code: 6004, + name: 'InvalidMakerFee', + msg: 'Maker fee must be zero', + }, + { + code: 6005, + name: 'InvalidTakerFee', + msg: 'Taker fee must be zero', + }, + { + code: 6006, + name: 'InvalidSeqNum', + msg: 'Seq num must be zero', + }, + { + code: 6007, + name: 'InvalidConsumeEventsAdmin', + msg: 'Consume events admin must be None', + }, + ], +}; diff --git a/packages/futarchy-ts/lib/idl/openbook_v2.ts b/packages/futarchy-ts/lib/idl/openbook_v2.ts new file mode 100644 index 00000000..8b8ad49b --- /dev/null +++ b/packages/futarchy-ts/lib/idl/openbook_v2.ts @@ -0,0 +1,7019 @@ +export interface OpenbookV2 { + version: '0.1.0'; + name: 'openbook_v2'; + instructions: [ + { + name: 'createMarket'; + docs: ['Create a [`Market`](crate::state::Market) for a given token pair.']; + accounts: [ + { + name: 'market'; + isMut: true; + isSigner: true; + }, + { + name: 'marketAuthority'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + docs: [ + 'Accounts are initialized by client,', + 'anchor discriminator is set first when ix exits,', + ]; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'payer'; + isMut: true; + isSigner: true; + }, + { + name: 'marketBaseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'baseMint'; + isMut: false; + isSigner: false; + }, + { + name: 'quoteMint'; + isMut: false; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'associatedTokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'oracleA'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'oracleB'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'collectFeeAdmin'; + isMut: false; + isSigner: false; + }, + { + name: 'openOrdersAdmin'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'consumeEventsAdmin'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'closeMarketAdmin'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'eventAuthority'; + isMut: false; + isSigner: false; + }, + { + name: 'program'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'name'; + type: 'string'; + }, + { + name: 'oracleConfig'; + type: { + defined: 'OracleConfigParams'; + }; + }, + { + name: 'quoteLotSize'; + type: 'i64'; + }, + { + name: 'baseLotSize'; + type: 'i64'; + }, + { + name: 'makerFee'; + type: 'i64'; + }, + { + name: 'takerFee'; + type: 'i64'; + }, + { + name: 'timeExpiry'; + type: 'i64'; + }, + ]; + }, + { + name: 'closeMarket'; + docs: [ + 'Close a [`Market`](crate::state::Market) (only', + '[`close_market_admin`](crate::state::Market::close_market_admin)).', + ]; + accounts: [ + { + name: 'closeMarketAdmin'; + isMut: false; + isSigner: true; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'solDestination'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'createOpenOrdersIndexer'; + docs: ['Create an [`OpenOrdersIndexer`](crate::state::OpenOrdersIndexer) account.']; + accounts: [ + { + name: 'payer'; + isMut: true; + isSigner: true; + }, + { + name: 'owner'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersIndexer'; + isMut: true; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'closeOpenOrdersIndexer'; + docs: ['Close an [`OpenOrdersIndexer`](crate::state::OpenOrdersIndexer) account.']; + accounts: [ + { + name: 'owner'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersIndexer'; + isMut: true; + isSigner: false; + }, + { + name: 'solDestination'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'createOpenOrdersAccount'; + docs: ['Create an [`OpenOrdersAccount`](crate::state::OpenOrdersAccount).']; + accounts: [ + { + name: 'payer'; + isMut: true; + isSigner: true; + }, + { + name: 'owner'; + isMut: false; + isSigner: true; + }, + { + name: 'delegateAccount'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'openOrdersIndexer'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: false; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'name'; + type: 'string'; + }, + ]; + }, + { + name: 'closeOpenOrdersAccount'; + docs: ['Close an [`OpenOrdersAccount`](crate::state::OpenOrdersAccount).']; + accounts: [ + { + name: 'payer'; + isMut: true; + isSigner: true; + }, + { + name: 'owner'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersIndexer'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'solDestination'; + isMut: true; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'placeOrder'; + docs: [ + 'Place an order.', + '', + 'Different types of orders have different effects on the order book,', + 'as described in [`PlaceOrderType`](crate::state::PlaceOrderType).', + '', + '`price_lots` refers to the price in lots: the number of quote lots', + 'per base lot. It is ignored for `PlaceOrderType::Market` orders.', + '', + '`expiry_timestamp` is a unix timestamp for when this order should', + 'expire. If 0 is passed in, the order will never expire. If the time', + 'is in the past, the instruction is skipped. Timestamps in the future', + 'are reduced to now + 65,535s.', + '', + '`limit` determines the maximum number of orders from the book to fill,', + 'and can be used to limit CU spent. When the limit is reached, processing', + 'stops and the instruction succeeds.', + ]; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAdmin'; + isMut: false; + isSigner: true; + isOptional: true; + }, + { + name: 'userTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'marketVault'; + isMut: true; + isSigner: false; + }, + { + name: 'oracleA'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'oracleB'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'args'; + type: { + defined: 'PlaceOrderArgs'; + }; + }, + ]; + returns: { + option: 'u128'; + }; + }, + { + name: 'editOrder'; + docs: ['Edit an order.']; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAdmin'; + isMut: false; + isSigner: true; + isOptional: true; + }, + { + name: 'userTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'marketVault'; + isMut: true; + isSigner: false; + }, + { + name: 'oracleA'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'oracleB'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'clientOrderId'; + type: 'u64'; + }, + { + name: 'expectedCancelSize'; + type: 'i64'; + }, + { + name: 'placeOrder'; + type: { + defined: 'PlaceOrderArgs'; + }; + }, + ]; + returns: { + option: 'u128'; + }; + }, + { + name: 'editOrderPegged'; + docs: ['Edit an order pegged.']; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAdmin'; + isMut: false; + isSigner: true; + isOptional: true; + }, + { + name: 'userTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'marketVault'; + isMut: true; + isSigner: false; + }, + { + name: 'oracleA'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'oracleB'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'clientOrderId'; + type: 'u64'; + }, + { + name: 'expectedCancelSize'; + type: 'i64'; + }, + { + name: 'placeOrder'; + type: { + defined: 'PlaceOrderPeggedArgs'; + }; + }, + ]; + returns: { + option: 'u128'; + }; + }, + { + name: 'cancelAndPlaceOrders'; + docs: ['Cancel orders and place multiple orders.']; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAdmin'; + isMut: false; + isSigner: true; + isOptional: true; + }, + { + name: 'userQuoteAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userBaseAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'marketBaseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'oracleA'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'oracleB'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'cancelClientOrdersIds'; + type: { + vec: 'u64'; + }; + }, + { + name: 'placeOrders'; + type: { + vec: { + defined: 'PlaceOrderArgs'; + }; + }; + }, + ]; + returns: { + vec: { + option: 'u128'; + }; + }; + }, + { + name: 'placeOrderPegged'; + docs: ['Place an oracle-peg order.']; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAdmin'; + isMut: false; + isSigner: true; + isOptional: true; + }, + { + name: 'userTokenAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'marketVault'; + isMut: true; + isSigner: false; + }, + { + name: 'oracleA'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'oracleB'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'args'; + type: { + defined: 'PlaceOrderPeggedArgs'; + }; + }, + ]; + returns: { + option: 'u128'; + }; + }, + { + name: 'placeTakeOrder'; + docs: [ + 'Place an order that shall take existing liquidity off of the book, not', + 'add a new order off the book.', + '', + 'This type of order allows for instant token settlement for the taker.', + ]; + accounts: [ + { + name: 'signer'; + isMut: true; + isSigner: true; + }, + { + name: 'penaltyPayer'; + isMut: true; + isSigner: true; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'marketAuthority'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + { + name: 'marketBaseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + { + name: 'userBaseAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userQuoteAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'referrerAccount'; + isMut: true; + isSigner: false; + isOptional: true; + }, + { + name: 'oracleA'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'oracleB'; + isMut: false; + isSigner: false; + isOptional: true; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'openOrdersAdmin'; + isMut: false; + isSigner: true; + isOptional: true; + }, + ]; + args: [ + { + name: 'args'; + type: { + defined: 'PlaceTakeOrderArgs'; + }; + }, + ]; + }, + { + name: 'consumeEvents'; + docs: [ + 'Process up to `limit` [events](crate::state::AnyEvent).', + '', + "When a user places a 'take' order, they do not know beforehand which", + "market maker will have placed the 'make' order that they get executed", + "against. This prevents them from passing in a market maker's", + '[`OpenOrdersAccount`](crate::state::OpenOrdersAccount), which is needed', + 'to credit/debit the relevant tokens to/from the maker. As such, Openbook', + "uses a 'crank' system, where `place_order` only emits events, and", + '`consume_events` handles token settlement.', + '', + 'Currently, there are two types of events: [`FillEvent`](crate::state::FillEvent)s', + 'and [`OutEvent`](crate::state::OutEvent)s.', + '', + 'A `FillEvent` is emitted when an order is filled, and it is handled by', + 'debiting whatever the taker is selling from the taker and crediting', + 'it to the maker, and debiting whatever the taker is buying from the', + 'maker and crediting it to the taker. Note that *no tokens are moved*,', + "these are just debits and credits to each party's [`Position`](crate::state::Position).", + '', + 'An `OutEvent` is emitted when a limit order needs to be removed from', + 'the book during a `place_order` invocation, and it is handled by', + 'crediting whatever the maker would have sold (quote token in a bid,', + 'base token in an ask) back to the maker.', + ]; + accounts: [ + { + name: 'consumeEventsAdmin'; + isMut: false; + isSigner: true; + isOptional: true; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + ]; + args: [ + { + name: 'limit'; + type: 'u64'; + }, + ]; + }, + { + name: 'consumeGivenEvents'; + docs: ['Process the [events](crate::state::AnyEvent) at the given positions.']; + accounts: [ + { + name: 'consumeEventsAdmin'; + isMut: false; + isSigner: true; + isOptional: true; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'eventHeap'; + isMut: true; + isSigner: false; + }, + ]; + args: [ + { + name: 'slots'; + type: { + vec: 'u64'; + }; + }, + ]; + }, + { + name: 'cancelOrder'; + docs: [ + 'Cancel an order by its `order_id`.', + '', + "Note that this doesn't emit an [`OutEvent`](crate::state::OutEvent) because a", + 'maker knows that they will be passing in their own [`OpenOrdersAccount`](crate::state::OpenOrdersAccount).', + ]; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + ]; + args: [ + { + name: 'orderId'; + type: 'u128'; + }, + ]; + }, + { + name: 'cancelOrderByClientOrderId'; + docs: [ + 'Cancel an order by its `client_order_id`.', + '', + "Note that this doesn't emit an [`OutEvent`](crate::state::OutEvent) because a", + 'maker knows that they will be passing in their own [`OpenOrdersAccount`](crate::state::OpenOrdersAccount).', + ]; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + ]; + args: [ + { + name: 'clientOrderId'; + type: 'u64'; + }, + ]; + returns: 'i64'; + }, + { + name: 'cancelAllOrders'; + docs: ['Cancel up to `limit` orders, optionally filtering by side']; + accounts: [ + { + name: 'signer'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + ]; + args: [ + { + name: 'sideOption'; + type: { + option: { + defined: 'Side'; + }; + }; + }, + { + name: 'limit'; + type: 'u8'; + }, + ]; + }, + { + name: 'deposit'; + docs: [ + "Deposit a certain amount of `base` and `quote` lamports into one's", + '[`Position`](crate::state::Position).', + '', + 'Makers might wish to `deposit`, rather than have actual tokens moved for', + 'each trade, in order to reduce CUs.', + ]; + accounts: [ + { + name: 'owner'; + isMut: false; + isSigner: true; + }, + { + name: 'userBaseAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userQuoteAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'marketBaseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'baseAmount'; + type: 'u64'; + }, + { + name: 'quoteAmount'; + type: 'u64'; + }, + ]; + }, + { + name: 'refill'; + docs: [ + 'Refill a certain amount of `base` and `quote` lamports. The amount being passed is the', + 'total lamports that the [`Position`](crate::state::Position) will have.', + '', + 'Makers might wish to `refill`, rather than have actual tokens moved for', + 'each trade, in order to reduce CUs.', + ]; + accounts: [ + { + name: 'owner'; + isMut: false; + isSigner: true; + }, + { + name: 'userBaseAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userQuoteAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'marketBaseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'baseAmount'; + type: 'u64'; + }, + { + name: 'quoteAmount'; + type: 'u64'; + }, + ]; + }, + { + name: 'settleFunds'; + docs: ['Withdraw any available tokens.']; + accounts: [ + { + name: 'owner'; + isMut: true; + isSigner: true; + }, + { + name: 'penaltyPayer'; + isMut: true; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'marketAuthority'; + isMut: false; + isSigner: false; + }, + { + name: 'marketBaseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'userBaseAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userQuoteAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'referrerAccount'; + isMut: true; + isSigner: false; + isOptional: true; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'settleFundsExpired'; + docs: [ + 'Withdraw any available tokens when the market is expired (only', + '[`close_market_admin`](crate::state::Market::close_market_admin)).', + ]; + accounts: [ + { + name: 'closeMarketAdmin'; + isMut: false; + isSigner: true; + }, + { + name: 'owner'; + isMut: true; + isSigner: true; + }, + { + name: 'penaltyPayer'; + isMut: true; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'marketAuthority'; + isMut: false; + isSigner: false; + }, + { + name: 'marketBaseVault'; + isMut: true; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'userBaseAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'userQuoteAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'referrerAccount'; + isMut: true; + isSigner: false; + isOptional: true; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'sweepFees'; + docs: ["Sweep fees, as a [`Market`](crate::state::Market)'s admin."]; + accounts: [ + { + name: 'collectFeeAdmin'; + isMut: false; + isSigner: true; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + { + name: 'marketAuthority'; + isMut: false; + isSigner: false; + }, + { + name: 'marketQuoteVault'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenReceiverAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'setDelegate'; + docs: [ + 'Update the [`delegate`](crate::state::OpenOrdersAccount::delegate) of an open orders account.', + ]; + accounts: [ + { + name: 'owner'; + isMut: true; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'delegateAccount'; + isMut: false; + isSigner: false; + isOptional: true; + }, + ]; + args: []; + }, + { + name: 'setMarketExpired'; + docs: [ + 'Set market to expired before pruning orders and closing the market (only', + '[`close_market_admin`](crate::state::Market::close_market_admin)).', + ]; + accounts: [ + { + name: 'closeMarketAdmin'; + isMut: false; + isSigner: true; + }, + { + name: 'market'; + isMut: true; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'pruneOrders'; + docs: [ + 'Remove orders from the book when the market is expired (only', + '[`close_market_admin`](crate::state::Market::close_market_admin)).', + ]; + accounts: [ + { + name: 'closeMarketAdmin'; + isMut: false; + isSigner: true; + }, + { + name: 'openOrdersAccount'; + isMut: true; + isSigner: false; + }, + { + name: 'market'; + isMut: false; + isSigner: false; + }, + { + name: 'bids'; + isMut: true; + isSigner: false; + }, + { + name: 'asks'; + isMut: true; + isSigner: false; + }, + ]; + args: [ + { + name: 'limit'; + type: 'u8'; + }, + ]; + }, + { + name: 'stubOracleCreate'; + accounts: [ + { + name: 'payer'; + isMut: true; + isSigner: true; + }, + { + name: 'owner'; + isMut: false; + isSigner: true; + }, + { + name: 'oracle'; + isMut: true; + isSigner: false; + }, + { + name: 'mint'; + isMut: false; + isSigner: false; + }, + { + name: 'systemProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: [ + { + name: 'price'; + type: 'f64'; + }, + ]; + }, + { + name: 'stubOracleClose'; + accounts: [ + { + name: 'owner'; + isMut: false; + isSigner: true; + }, + { + name: 'oracle'; + isMut: true; + isSigner: false; + }, + { + name: 'solDestination'; + isMut: true; + isSigner: false; + }, + { + name: 'tokenProgram'; + isMut: false; + isSigner: false; + }, + ]; + args: []; + }, + { + name: 'stubOracleSet'; + accounts: [ + { + name: 'owner'; + isMut: false; + isSigner: true; + }, + { + name: 'oracle'; + isMut: true; + isSigner: false; + }, + ]; + args: [ + { + name: 'price'; + type: 'f64'; + }, + ]; + }, + ]; + accounts: [ + { + name: 'market'; + type: { + kind: 'struct'; + fields: [ + { + name: 'bump'; + docs: ['PDA bump']; + type: 'u8'; + }, + { + name: 'baseDecimals'; + docs: [ + 'Number of decimals used for the base token.', + '', + "Used to convert the oracle's price into a native/native price.", + ]; + type: 'u8'; + }, + { + name: 'quoteDecimals'; + type: 'u8'; + }, + { + name: 'padding1'; + type: { + array: ['u8', 5]; + }; + }, + { + name: 'marketAuthority'; + type: 'publicKey'; + }, + { + name: 'timeExpiry'; + docs: ['No expiry = 0. Market will expire and no trading allowed after time_expiry']; + type: 'i64'; + }, + { + name: 'collectFeeAdmin'; + docs: ['Admin who can collect fees from the market']; + type: 'publicKey'; + }, + { + name: 'openOrdersAdmin'; + docs: ['Admin who must sign off on all order creations']; + type: { + defined: 'NonZeroPubkeyOption'; + }; + }, + { + name: 'consumeEventsAdmin'; + docs: ['Admin who must sign off on all event consumptions']; + type: { + defined: 'NonZeroPubkeyOption'; + }; + }, + { + name: 'closeMarketAdmin'; + docs: ['Admin who can set market expired, prune orders and close the market']; + type: { + defined: 'NonZeroPubkeyOption'; + }; + }, + { + name: 'name'; + docs: ['Name. Trailing zero bytes are ignored.']; + type: { + array: ['u8', 16]; + }; + }, + { + name: 'bids'; + docs: ['Address of the BookSide account for bids']; + type: 'publicKey'; + }, + { + name: 'asks'; + docs: ['Address of the BookSide account for asks']; + type: 'publicKey'; + }, + { + name: 'eventHeap'; + docs: ['Address of the EventHeap account']; + type: 'publicKey'; + }, + { + name: 'oracleA'; + docs: ['Oracles account address']; + type: { + defined: 'NonZeroPubkeyOption'; + }; + }, + { + name: 'oracleB'; + type: { + defined: 'NonZeroPubkeyOption'; + }; + }, + { + name: 'oracleConfig'; + docs: ['Oracle configuration']; + type: { + defined: 'OracleConfig'; + }; + }, + { + name: 'quoteLotSize'; + docs: [ + 'Number of quote native in a quote lot. Must be a power of 10.', + '', + 'Primarily useful for increasing the tick size on the market: A lot price', + 'of 1 becomes a native price of quote_lot_size/base_lot_size becomes a', + 'ui price of quote_lot_size*base_decimals/base_lot_size/quote_decimals.', + ]; + type: 'i64'; + }, + { + name: 'baseLotSize'; + docs: [ + 'Number of base native in a base lot. Must be a power of 10.', + '', + 'Example: If base decimals for the underlying asset is 6, base lot size', + 'is 100 and and base position lots is 10_000 then base position native is', + '1_000_000 and base position ui is 1.', + ]; + type: 'i64'; + }, + { + name: 'seqNum'; + docs: ['Total number of orders seen']; + type: 'u64'; + }, + { + name: 'registrationTime'; + docs: ['Timestamp in seconds that the market was registered at.']; + type: 'i64'; + }, + { + name: 'makerFee'; + docs: [ + 'Fees', + '', + 'Fee (in 10^-6) when matching maker orders.', + 'maker_fee < 0 it means some of the taker_fees goes to the maker', + 'maker_fee > 0, it means no taker_fee to the maker, and maker fee goes to the referral', + ]; + type: 'i64'; + }, + { + name: 'takerFee'; + docs: ['Fee (in 10^-6) for taker orders, always >= 0.']; + type: 'i64'; + }, + { + name: 'feesAccrued'; + docs: ['Total fees accrued in native quote']; + type: 'u128'; + }, + { + name: 'feesToReferrers'; + docs: ['Total fees settled in native quote']; + type: 'u128'; + }, + { + name: 'referrerRebatesAccrued'; + docs: ['Referrer rebates to be distributed']; + type: 'u64'; + }, + { + name: 'feesAvailable'; + docs: ['Fees generated and available to withdraw via sweep_fees']; + type: 'u64'; + }, + { + name: 'makerVolume'; + docs: ['Cumulative maker volume (same as taker volume) in quote native units']; + type: 'u128'; + }, + { + name: 'takerVolumeWoOo'; + docs: ['Cumulative taker volume in quote native units due to place take orders']; + type: 'u128'; + }, + { + name: 'baseMint'; + type: 'publicKey'; + }, + { + name: 'quoteMint'; + type: 'publicKey'; + }, + { + name: 'marketBaseVault'; + type: 'publicKey'; + }, + { + name: 'baseDepositTotal'; + type: 'u64'; + }, + { + name: 'marketQuoteVault'; + type: 'publicKey'; + }, + { + name: 'quoteDepositTotal'; + type: 'u64'; + }, + { + name: 'reserved'; + type: { + array: ['u8', 128]; + }; + }, + ]; + }; + }, + { + name: 'openOrdersAccount'; + type: { + kind: 'struct'; + fields: [ + { + name: 'owner'; + type: 'publicKey'; + }, + { + name: 'market'; + type: 'publicKey'; + }, + { + name: 'name'; + type: { + array: ['u8', 32]; + }; + }, + { + name: 'delegate'; + type: { + defined: 'NonZeroPubkeyOption'; + }; + }, + { + name: 'accountNum'; + type: 'u32'; + }, + { + name: 'bump'; + type: 'u8'; + }, + { + name: 'padding'; + type: { + array: ['u8', 3]; + }; + }, + { + name: 'position'; + type: { + defined: 'Position'; + }; + }, + { + name: 'openOrders'; + type: { + array: [ + { + defined: 'OpenOrder'; + }, + 24, + ]; + }; + }, + ]; + }; + }, + { + name: 'openOrdersIndexer'; + type: { + kind: 'struct'; + fields: [ + { + name: 'bump'; + type: 'u8'; + }, + { + name: 'createdCounter'; + type: 'u32'; + }, + { + name: 'addresses'; + type: { + vec: 'publicKey'; + }; + }, + ]; + }; + }, + { + name: 'stubOracle'; + type: { + kind: 'struct'; + fields: [ + { + name: 'owner'; + type: 'publicKey'; + }, + { + name: 'mint'; + type: 'publicKey'; + }, + { + name: 'price'; + type: 'f64'; + }, + { + name: 'lastUpdateTs'; + type: 'i64'; + }, + { + name: 'lastUpdateSlot'; + type: 'u64'; + }, + { + name: 'deviation'; + type: 'f64'; + }, + { + name: 'reserved'; + type: { + array: ['u8', 104]; + }; + }, + ]; + }; + }, + { + name: 'bookSide'; + type: { + kind: 'struct'; + fields: [ + { + name: 'roots'; + type: { + array: [ + { + defined: 'OrderTreeRoot'; + }, + 2, + ]; + }; + }, + { + name: 'reservedRoots'; + type: { + array: [ + { + defined: 'OrderTreeRoot'; + }, + 4, + ]; + }; + }, + { + name: 'reserved'; + type: { + array: ['u8', 256]; + }; + }, + { + name: 'nodes'; + type: { + defined: 'OrderTreeNodes'; + }; + }, + ]; + }; + }, + { + name: 'eventHeap'; + docs: [ + 'Container for the different EventTypes.', + '', + 'Events are stored in a fixed-array of nodes. Free nodes are connected by a single-linked list', + 'starting at free_head while used nodes form a circular doubly-linked list starting at', + 'used_head.', + ]; + type: { + kind: 'struct'; + fields: [ + { + name: 'header'; + type: { + defined: 'EventHeapHeader'; + }; + }, + { + name: 'nodes'; + type: { + array: [ + { + defined: 'EventNode'; + }, + 600, + ]; + }; + }, + { + name: 'reserved'; + type: { + array: ['u8', 64]; + }; + }, + ]; + }; + }, + ]; + types: [ + { + name: 'NonZeroPubkeyOption'; + docs: ['Like `Option`, but implemented for `Pubkey` to be used with `zero_copy`']; + type: { + kind: 'struct'; + fields: [ + { + name: 'key'; + type: 'publicKey'; + }, + ]; + }; + }, + { + name: 'Position'; + type: { + kind: 'struct'; + fields: [ + { + name: 'bidsBaseLots'; + docs: ['Base lots in open bids']; + type: 'i64'; + }, + { + name: 'asksBaseLots'; + docs: ['Base lots in open asks']; + type: 'i64'; + }, + { + name: 'baseFreeNative'; + type: 'u64'; + }, + { + name: 'quoteFreeNative'; + type: 'u64'; + }, + { + name: 'lockedMakerFees'; + type: 'u64'; + }, + { + name: 'referrerRebatesAvailable'; + type: 'u64'; + }, + { + name: 'penaltyHeapCount'; + docs: [ + 'Count of ixs when events are added to the heap', + 'To avoid this, send remaining accounts in order to process the events', + ]; + type: 'u64'; + }, + { + name: 'makerVolume'; + docs: ['Cumulative maker volume in quote native units (display only)']; + type: 'u128'; + }, + { + name: 'takerVolume'; + docs: ['Cumulative taker volume in quote native units (display only)']; + type: 'u128'; + }, + { + name: 'reserved'; + type: { + array: ['u8', 72]; + }; + }, + ]; + }; + }, + { + name: 'OpenOrder'; + type: { + kind: 'struct'; + fields: [ + { + name: 'id'; + type: 'u128'; + }, + { + name: 'clientId'; + type: 'u64'; + }, + { + name: 'lockedPrice'; + docs: ["Price at which user's assets were locked"]; + type: 'i64'; + }, + { + name: 'isFree'; + type: 'u8'; + }, + { + name: 'sideAndTree'; + type: 'u8'; + }, + { + name: 'padding'; + type: { + array: ['u8', 6]; + }; + }, + ]; + }; + }, + { + name: 'OracleConfig'; + type: { + kind: 'struct'; + fields: [ + { + name: 'confFilter'; + type: 'f64'; + }, + { + name: 'maxStalenessSlots'; + type: 'i64'; + }, + { + name: 'reserved'; + type: { + array: ['u8', 72]; + }; + }, + ]; + }; + }, + { + name: 'OracleConfigParams'; + type: { + kind: 'struct'; + fields: [ + { + name: 'confFilter'; + type: 'f32'; + }, + { + name: 'maxStalenessSlots'; + type: { + option: 'u32'; + }; + }, + ]; + }; + }, + { + name: 'EventHeapHeader'; + type: { + kind: 'struct'; + fields: [ + { + name: 'freeHead'; + type: 'u16'; + }, + { + name: 'usedHead'; + type: 'u16'; + }, + { + name: 'count'; + type: 'u16'; + }, + { + name: 'padd'; + type: 'u16'; + }, + { + name: 'seqNum'; + type: 'u64'; + }, + ]; + }; + }, + { + name: 'EventNode'; + type: { + kind: 'struct'; + fields: [ + { + name: 'next'; + type: 'u16'; + }, + { + name: 'prev'; + type: 'u16'; + }, + { + name: 'pad'; + type: { + array: ['u8', 4]; + }; + }, + { + name: 'event'; + type: { + defined: 'AnyEvent'; + }; + }, + ]; + }; + }, + { + name: 'AnyEvent'; + type: { + kind: 'struct'; + fields: [ + { + name: 'eventType'; + type: 'u8'; + }, + { + name: 'padding'; + type: { + array: ['u8', 143]; + }; + }, + ]; + }; + }, + { + name: 'FillEvent'; + type: { + kind: 'struct'; + fields: [ + { + name: 'eventType'; + type: 'u8'; + }, + { + name: 'takerSide'; + type: 'u8'; + }, + { + name: 'makerOut'; + type: 'u8'; + }, + { + name: 'makerSlot'; + type: 'u8'; + }, + { + name: 'padding'; + type: { + array: ['u8', 4]; + }; + }, + { + name: 'timestamp'; + type: 'u64'; + }, + { + name: 'seqNum'; + type: 'u64'; + }, + { + name: 'maker'; + type: 'publicKey'; + }, + { + name: 'makerTimestamp'; + type: 'u64'; + }, + { + name: 'taker'; + type: 'publicKey'; + }, + { + name: 'takerClientOrderId'; + type: 'u64'; + }, + { + name: 'price'; + type: 'i64'; + }, + { + name: 'pegLimit'; + type: 'i64'; + }, + { + name: 'quantity'; + type: 'i64'; + }, + { + name: 'makerClientOrderId'; + type: 'u64'; + }, + { + name: 'reserved'; + type: { + array: ['u8', 8]; + }; + }, + ]; + }; + }, + { + name: 'OutEvent'; + type: { + kind: 'struct'; + fields: [ + { + name: 'eventType'; + type: 'u8'; + }, + { + name: 'side'; + type: 'u8'; + }, + { + name: 'ownerSlot'; + type: 'u8'; + }, + { + name: 'padding0'; + type: { + array: ['u8', 5]; + }; + }, + { + name: 'timestamp'; + type: 'u64'; + }, + { + name: 'seqNum'; + type: 'u64'; + }, + { + name: 'owner'; + type: 'publicKey'; + }, + { + name: 'quantity'; + type: 'i64'; + }, + { + name: 'padding1'; + type: { + array: ['u8', 80]; + }; + }, + ]; + }; + }, + { + name: 'InnerNode'; + docs: [ + 'InnerNodes and LeafNodes compose the binary tree of orders.', + '', + 'Each InnerNode has exactly two children, which are either InnerNodes themselves,', + 'or LeafNodes. The children share the top `prefix_len` bits of `key`. The left', + 'child has a 0 in the next bit, and the right a 1.', + ]; + type: { + kind: 'struct'; + fields: [ + { + name: 'tag'; + type: 'u8'; + }, + { + name: 'padding'; + type: { + array: ['u8', 3]; + }; + }, + { + name: 'prefixLen'; + docs: [ + 'number of highest `key` bits that all children share', + "e.g. if it's 2, the two highest bits of `key` will be the same on all children", + ]; + type: 'u32'; + }, + { + name: 'key'; + docs: ['only the top `prefix_len` bits of `key` are relevant']; + type: 'u128'; + }, + { + name: 'children'; + docs: ['indexes into `BookSide::nodes`']; + type: { + array: ['u32', 2]; + }; + }, + { + name: 'childEarliestExpiry'; + docs: [ + 'The earliest expiry timestamp for the left and right subtrees.', + '', + 'Needed to be able to find and remove expired orders without having to', + 'iterate through the whole bookside.', + ]; + type: { + array: ['u64', 2]; + }; + }, + { + name: 'reserved'; + type: { + array: ['u8', 40]; + }; + }, + ]; + }; + }, + { + name: 'LeafNode'; + docs: ['LeafNodes represent an order in the binary tree']; + type: { + kind: 'struct'; + fields: [ + { + name: 'tag'; + docs: ['NodeTag']; + type: 'u8'; + }, + { + name: 'ownerSlot'; + docs: ["Index into the owning OpenOrdersAccount's OpenOrders"]; + type: 'u8'; + }, + { + name: 'timeInForce'; + docs: [ + 'Time in seconds after `timestamp` at which the order expires.', + 'A value of 0 means no expiry.', + ]; + type: 'u16'; + }, + { + name: 'padding'; + type: { + array: ['u8', 4]; + }; + }, + { + name: 'key'; + docs: ['The binary tree key, see new_node_key()']; + type: 'u128'; + }, + { + name: 'owner'; + docs: ['Address of the owning OpenOrdersAccount']; + type: 'publicKey'; + }, + { + name: 'quantity'; + docs: ['Number of base lots to buy or sell, always >=1']; + type: 'i64'; + }, + { + name: 'timestamp'; + docs: ['The time the order was placed']; + type: 'u64'; + }, + { + name: 'pegLimit'; + docs: [ + 'If the effective price of an oracle pegged order exceeds this limit,', + 'it will be considered invalid and may be removed.', + '', + 'Only applicable in the oracle_pegged OrderTree', + ]; + type: 'i64'; + }, + { + name: 'clientOrderId'; + docs: ['User defined id for this order, used in FillEvents']; + type: 'u64'; + }, + ]; + }; + }, + { + name: 'AnyNode'; + type: { + kind: 'struct'; + fields: [ + { + name: 'tag'; + type: 'u8'; + }, + { + name: 'data'; + type: { + array: ['u8', 87]; + }; + }, + ]; + }; + }, + { + name: 'OrderTreeRoot'; + type: { + kind: 'struct'; + fields: [ + { + name: 'maybeNode'; + type: 'u32'; + }, + { + name: 'leafCount'; + type: 'u32'; + }, + ]; + }; + }, + { + name: 'OrderTreeNodes'; + docs: [ + 'A binary tree on AnyNode::key()', + '', + 'The key encodes the price in the top 64 bits.', + ]; + type: { + kind: 'struct'; + fields: [ + { + name: 'orderTreeType'; + type: 'u8'; + }, + { + name: 'padding'; + type: { + array: ['u8', 3]; + }; + }, + { + name: 'bumpIndex'; + type: 'u32'; + }, + { + name: 'freeListLen'; + type: 'u32'; + }, + { + name: 'freeListHead'; + type: 'u32'; + }, + { + name: 'reserved'; + type: { + array: ['u8', 512]; + }; + }, + { + name: 'nodes'; + type: { + array: [ + { + defined: 'AnyNode'; + }, + 1024, + ]; + }; + }, + ]; + }; + }, + { + name: 'I80F48'; + docs: [ + 'Nothing in Rust shall use these types. They only exist so that the Anchor IDL', + 'knows about them and typescript can deserialize it.', + ]; + type: { + kind: 'struct'; + fields: [ + { + name: 'val'; + type: 'i128'; + }, + ]; + }; + }, + { + name: 'PlaceOrderArgs'; + type: { + kind: 'struct'; + fields: [ + { + name: 'side'; + type: { + defined: 'Side'; + }; + }, + { + name: 'priceLots'; + type: 'i64'; + }, + { + name: 'maxBaseLots'; + type: 'i64'; + }, + { + name: 'maxQuoteLotsIncludingFees'; + type: 'i64'; + }, + { + name: 'clientOrderId'; + type: 'u64'; + }, + { + name: 'orderType'; + type: { + defined: 'PlaceOrderType'; + }; + }, + { + name: 'expiryTimestamp'; + type: 'u64'; + }, + { + name: 'selfTradeBehavior'; + type: { + defined: 'SelfTradeBehavior'; + }; + }, + { + name: 'limit'; + type: 'u8'; + }, + ]; + }; + }, + { + name: 'PlaceOrderPeggedArgs'; + type: { + kind: 'struct'; + fields: [ + { + name: 'side'; + type: { + defined: 'Side'; + }; + }, + { + name: 'priceOffsetLots'; + type: 'i64'; + }, + { + name: 'pegLimit'; + type: 'i64'; + }, + { + name: 'maxBaseLots'; + type: 'i64'; + }, + { + name: 'maxQuoteLotsIncludingFees'; + type: 'i64'; + }, + { + name: 'clientOrderId'; + type: 'u64'; + }, + { + name: 'orderType'; + type: { + defined: 'PlaceOrderType'; + }; + }, + { + name: 'expiryTimestamp'; + type: 'u64'; + }, + { + name: 'selfTradeBehavior'; + type: { + defined: 'SelfTradeBehavior'; + }; + }, + { + name: 'limit'; + type: 'u8'; + }, + ]; + }; + }, + { + name: 'PlaceTakeOrderArgs'; + type: { + kind: 'struct'; + fields: [ + { + name: 'side'; + type: { + defined: 'Side'; + }; + }, + { + name: 'priceLots'; + type: 'i64'; + }, + { + name: 'maxBaseLots'; + type: 'i64'; + }, + { + name: 'maxQuoteLotsIncludingFees'; + type: 'i64'; + }, + { + name: 'orderType'; + type: { + defined: 'PlaceOrderType'; + }; + }, + { + name: 'limit'; + type: 'u8'; + }, + ]; + }; + }, + { + name: 'OracleType'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Pyth'; + }, + { + name: 'Stub'; + }, + { + name: 'SwitchboardV1'; + }, + { + name: 'SwitchboardV2'; + }, + { + name: 'RaydiumCLMM'; + }, + ]; + }; + }, + { + name: 'OrderState'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Valid'; + }, + { + name: 'Invalid'; + }, + { + name: 'Skipped'; + }, + ]; + }; + }, + { + name: 'BookSideOrderTree'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Fixed'; + }, + { + name: 'OraclePegged'; + }, + ]; + }; + }, + { + name: 'EventType'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Fill'; + }, + { + name: 'Out'; + }, + ]; + }; + }, + { + name: 'NodeTag'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Uninitialized'; + }, + { + name: 'InnerNode'; + }, + { + name: 'LeafNode'; + }, + { + name: 'FreeNode'; + }, + { + name: 'LastFreeNode'; + }, + ]; + }; + }, + { + name: 'PlaceOrderType'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Limit'; + }, + { + name: 'ImmediateOrCancel'; + }, + { + name: 'PostOnly'; + }, + { + name: 'Market'; + }, + { + name: 'PostOnlySlide'; + }, + ]; + }; + }, + { + name: 'PostOrderType'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Limit'; + }, + { + name: 'PostOnly'; + }, + { + name: 'PostOnlySlide'; + }, + ]; + }; + }, + { + name: 'SelfTradeBehavior'; + docs: [ + 'Self trade behavior controls how taker orders interact with resting limit orders of the same account.', + 'This setting has no influence on placing a resting or oracle pegged limit order that does not match', + "immediately, instead it's the responsibility of the user to correctly configure his taker orders.", + ]; + type: { + kind: 'enum'; + variants: [ + { + name: 'DecrementTake'; + }, + { + name: 'CancelProvide'; + }, + { + name: 'AbortTransaction'; + }, + ]; + }; + }, + { + name: 'Side'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Bid'; + }, + { + name: 'Ask'; + }, + ]; + }; + }, + { + name: 'SideAndOrderTree'; + docs: ["SideAndOrderTree is a storage optimization, so we don't need two bytes for the data"]; + type: { + kind: 'enum'; + variants: [ + { + name: 'BidFixed'; + }, + { + name: 'AskFixed'; + }, + { + name: 'BidOraclePegged'; + }, + { + name: 'AskOraclePegged'; + }, + ]; + }; + }, + { + name: 'OrderParams'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Market'; + }, + { + name: 'ImmediateOrCancel'; + fields: [ + { + name: 'price_lots'; + type: 'i64'; + }, + ]; + }, + { + name: 'Fixed'; + fields: [ + { + name: 'price_lots'; + type: 'i64'; + }, + { + name: 'order_type'; + type: { + defined: 'PostOrderType'; + }; + }, + ]; + }, + { + name: 'OraclePegged'; + fields: [ + { + name: 'price_offset_lots'; + type: 'i64'; + }, + { + name: 'order_type'; + type: { + defined: 'PostOrderType'; + }; + }, + { + name: 'peg_limit'; + type: 'i64'; + }, + ]; + }, + ]; + }; + }, + { + name: 'OrderTreeType'; + type: { + kind: 'enum'; + variants: [ + { + name: 'Bids'; + }, + { + name: 'Asks'; + }, + ]; + }; + }, + ]; + events: [ + { + name: 'DepositLog'; + fields: [ + { + name: 'openOrdersAccount'; + type: 'publicKey'; + index: false; + }, + { + name: 'signer'; + type: 'publicKey'; + index: false; + }, + { + name: 'baseAmount'; + type: 'u64'; + index: false; + }, + { + name: 'quoteAmount'; + type: 'u64'; + index: false; + }, + ]; + }, + { + name: 'FillLog'; + fields: [ + { + name: 'market'; + type: 'publicKey'; + index: false; + }, + { + name: 'takerSide'; + type: 'u8'; + index: false; + }, + { + name: 'makerSlot'; + type: 'u8'; + index: false; + }, + { + name: 'makerOut'; + type: 'bool'; + index: false; + }, + { + name: 'timestamp'; + type: 'u64'; + index: false; + }, + { + name: 'seqNum'; + type: 'u64'; + index: false; + }, + { + name: 'maker'; + type: 'publicKey'; + index: false; + }, + { + name: 'makerClientOrderId'; + type: 'u64'; + index: false; + }, + { + name: 'makerFee'; + type: 'i64'; + index: false; + }, + { + name: 'makerTimestamp'; + type: 'u64'; + index: false; + }, + { + name: 'taker'; + type: 'publicKey'; + index: false; + }, + { + name: 'takerClientOrderId'; + type: 'u64'; + index: false; + }, + { + name: 'takerFee'; + type: 'i64'; + index: false; + }, + { + name: 'price'; + type: 'i64'; + index: false; + }, + { + name: 'quantity'; + type: 'i64'; + index: false; + }, + ]; + }, + { + name: 'MarketMetaDataLog'; + fields: [ + { + name: 'market'; + type: 'publicKey'; + index: false; + }, + { + name: 'name'; + type: 'string'; + index: false; + }, + { + name: 'baseMint'; + type: 'publicKey'; + index: false; + }, + { + name: 'quoteMint'; + type: 'publicKey'; + index: false; + }, + { + name: 'baseDecimals'; + type: 'u8'; + index: false; + }, + { + name: 'quoteDecimals'; + type: 'u8'; + index: false; + }, + { + name: 'baseLotSize'; + type: 'i64'; + index: false; + }, + { + name: 'quoteLotSize'; + type: 'i64'; + index: false; + }, + ]; + }, + { + name: 'TotalOrderFillEvent'; + fields: [ + { + name: 'side'; + type: 'u8'; + index: false; + }, + { + name: 'taker'; + type: 'publicKey'; + index: false; + }, + { + name: 'totalQuantityPaid'; + type: 'u64'; + index: false; + }, + { + name: 'totalQuantityReceived'; + type: 'u64'; + index: false; + }, + { + name: 'fees'; + type: 'u64'; + index: false; + }, + ]; + }, + { + name: 'SetDelegateLog'; + fields: [ + { + name: 'openOrdersAccount'; + type: 'publicKey'; + index: false; + }, + { + name: 'delegate'; + type: { + option: 'publicKey'; + }; + index: false; + }, + ]; + }, + { + name: 'SettleFundsLog'; + fields: [ + { + name: 'openOrdersAccount'; + type: 'publicKey'; + index: false; + }, + { + name: 'baseNative'; + type: 'u64'; + index: false; + }, + { + name: 'quoteNative'; + type: 'u64'; + index: false; + }, + { + name: 'referrerRebate'; + type: 'u64'; + index: false; + }, + { + name: 'referrer'; + type: { + option: 'publicKey'; + }; + index: false; + }, + ]; + }, + { + name: 'SweepFeesLog'; + fields: [ + { + name: 'market'; + type: 'publicKey'; + index: false; + }, + { + name: 'amount'; + type: 'u64'; + index: false; + }, + { + name: 'receiver'; + type: 'publicKey'; + index: false; + }, + ]; + }, + { + name: 'OpenOrdersPositionLog'; + fields: [ + { + name: 'owner'; + type: 'publicKey'; + index: false; + }, + { + name: 'openOrdersAccountNum'; + type: 'u32'; + index: false; + }, + { + name: 'market'; + type: 'publicKey'; + index: false; + }, + { + name: 'bidsBaseLots'; + type: 'i64'; + index: false; + }, + { + name: 'asksBaseLots'; + type: 'i64'; + index: false; + }, + { + name: 'baseFreeNative'; + type: 'u64'; + index: false; + }, + { + name: 'quoteFreeNative'; + type: 'u64'; + index: false; + }, + { + name: 'lockedMakerFees'; + type: 'u64'; + index: false; + }, + { + name: 'referrerRebatesAvailable'; + type: 'u64'; + index: false; + }, + { + name: 'makerVolume'; + type: 'u128'; + index: false; + }, + { + name: 'takerVolume'; + type: 'u128'; + index: false; + }, + ]; + }, + ]; + errors: [ + { + code: 6000; + name: 'SomeError'; + msg: ''; + }, + { + code: 6001; + name: 'InvalidInputNameLength'; + msg: 'Name lenght above limit'; + }, + { + code: 6002; + name: 'InvalidInputMarketExpired'; + msg: 'Market cannot be created as expired'; + }, + { + code: 6003; + name: 'InvalidInputMarketFees'; + msg: 'Taker fees should be positive and if maker fees are negative, greater or equal to their abs value'; + }, + { + code: 6004; + name: 'InvalidInputLots'; + msg: 'Lots cannot be negative'; + }, + { + code: 6005; + name: 'InvalidInputLotsSize'; + msg: 'Lots size above market limits'; + }, + { + code: 6006; + name: 'InvalidInputOrdersAmounts'; + msg: 'Input amounts above limits'; + }, + { + code: 6007; + name: 'InvalidInputCancelSize'; + msg: 'Price lots should be greater than zero'; + }, + { + code: 6008; + name: 'InvalidInputPriceLots'; + msg: 'Expected cancel size should be greater than zero'; + }, + { + code: 6009; + name: 'InvalidInputPegLimit'; + msg: 'Peg limit should be greater than zero'; + }, + { + code: 6010; + name: 'InvalidInputOrderType'; + msg: 'The order type is invalid. A taker order must be Market or ImmediateOrCancel'; + }, + { + code: 6011; + name: 'InvalidInputOrderId'; + msg: 'Order id cannot be zero'; + }, + { + code: 6012; + name: 'InvalidInputHeapSlots'; + msg: 'Slot above heap limit'; + }, + { + code: 6013; + name: 'InvalidOracleTypes'; + msg: 'Cannot combine two oracles of different providers'; + }, + { + code: 6014; + name: 'InvalidSecondOracle'; + msg: 'Cannot configure secondary oracle without primary'; + }, + { + code: 6015; + name: 'NoCloseMarketAdmin'; + msg: 'This market does not have a `close_market_admin` and thus cannot be closed.'; + }, + { + code: 6016; + name: 'InvalidCloseMarketAdmin'; + msg: "The signer of this transaction is not this market's `close_market_admin`."; + }, + { + code: 6017; + name: 'InvalidOpenOrdersAdmin'; + msg: 'The `open_orders_admin` required by this market to sign all instructions that creates orders is missing or is not valid'; + }, + { + code: 6018; + name: 'InvalidConsumeEventsAdmin'; + msg: 'The `consume_events_admin` required by this market to sign all instructions that consume events is missing or is not valid'; + }, + { + code: 6019; + name: 'InvalidMarketVault'; + msg: 'Provided `market_vault` is invalid'; + }, + { + code: 6020; + name: 'IndexerActiveOO'; + msg: 'Cannot be closed due to the existence of open orders accounts'; + }, + { + code: 6021; + name: 'OraclePegInvalidOracleState'; + msg: 'Cannot place a peg order due to invalid oracle state'; + }, + { + code: 6022; + name: 'UnknownOracleType'; + msg: 'oracle type cannot be determined'; + }, + { + code: 6023; + name: 'OracleConfidence'; + msg: 'an oracle does not reach the confidence threshold'; + }, + { + code: 6024; + name: 'OracleStale'; + msg: 'an oracle is stale'; + }, + { + code: 6025; + name: 'OrderIdNotFound'; + msg: 'Order id not found on the orderbook'; + }, + { + code: 6026; + name: 'EventHeapContainsElements'; + msg: "Event heap contains elements and market can't be closed"; + }, + { + code: 6027; + name: 'InvalidOrderPostIOC'; + msg: 'ImmediateOrCancel is not a PostOrderType'; + }, + { + code: 6028; + name: 'InvalidOrderPostMarket'; + msg: 'Market is not a PostOrderType'; + }, + { + code: 6029; + name: 'WouldSelfTrade'; + msg: 'would self trade'; + }, + { + code: 6030; + name: 'MarketHasExpired'; + msg: 'The Market has already expired.'; + }, + { + code: 6031; + name: 'InvalidPriceLots'; + msg: 'Price lots should be greater than zero'; + }, + { + code: 6032; + name: 'InvalidOraclePrice'; + msg: 'Oracle price above market limits'; + }, + { + code: 6033; + name: 'MarketHasNotExpired'; + msg: 'The Market has not expired yet.'; + }, + { + code: 6034; + name: 'NoOwnerOrDelegate'; + msg: 'No correct owner or delegate.'; + }, + { + code: 6035; + name: 'NoOwner'; + msg: 'No correct owner'; + }, + { + code: 6036; + name: 'OpenOrdersFull'; + msg: 'No free order index in open orders account'; + }, + { + code: 6037; + name: 'BookContainsElements'; + msg: 'Book contains elements'; + }, + { + code: 6038; + name: 'OpenOrdersOrderNotFound'; + msg: 'Could not find order in user account'; + }, + { + code: 6039; + name: 'InvalidPostAmount'; + msg: 'Amount to post above book limits'; + }, + { + code: 6040; + name: 'DisabledOraclePeg'; + msg: 'Oracle peg orders are not enabled for this market'; + }, + { + code: 6041; + name: 'NonEmptyMarket'; + msg: 'Cannot close a non-empty market'; + }, + { + code: 6042; + name: 'NonEmptyOpenOrdersPosition'; + msg: 'Cannot close a non-empty open orders account'; + }, + ]; +} + +export const IDL: OpenbookV2 = { + version: '0.1.0', + name: 'openbook_v2', + instructions: [ + { + name: 'createMarket', + docs: ['Create a [`Market`](crate::state::Market) for a given token pair.'], + accounts: [ + { + name: 'market', + isMut: true, + isSigner: true, + }, + { + name: 'marketAuthority', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + docs: [ + 'Accounts are initialized by client,', + 'anchor discriminator is set first when ix exits,', + ], + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'marketBaseVault', + isMut: true, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'baseMint', + isMut: false, + isSigner: false, + }, + { + name: 'quoteMint', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'associatedTokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'oracleA', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'oracleB', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'collectFeeAdmin', + isMut: false, + isSigner: false, + }, + { + name: 'openOrdersAdmin', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'consumeEventsAdmin', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'closeMarketAdmin', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'eventAuthority', + isMut: false, + isSigner: false, + }, + { + name: 'program', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'name', + type: 'string', + }, + { + name: 'oracleConfig', + type: { + defined: 'OracleConfigParams', + }, + }, + { + name: 'quoteLotSize', + type: 'i64', + }, + { + name: 'baseLotSize', + type: 'i64', + }, + { + name: 'makerFee', + type: 'i64', + }, + { + name: 'takerFee', + type: 'i64', + }, + { + name: 'timeExpiry', + type: 'i64', + }, + ], + }, + { + name: 'closeMarket', + docs: [ + 'Close a [`Market`](crate::state::Market) (only', + '[`close_market_admin`](crate::state::Market::close_market_admin)).', + ], + accounts: [ + { + name: 'closeMarketAdmin', + isMut: false, + isSigner: true, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'solDestination', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'createOpenOrdersIndexer', + docs: ['Create an [`OpenOrdersIndexer`](crate::state::OpenOrdersIndexer) account.'], + accounts: [ + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'owner', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersIndexer', + isMut: true, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'closeOpenOrdersIndexer', + docs: ['Close an [`OpenOrdersIndexer`](crate::state::OpenOrdersIndexer) account.'], + accounts: [ + { + name: 'owner', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersIndexer', + isMut: true, + isSigner: false, + }, + { + name: 'solDestination', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'createOpenOrdersAccount', + docs: ['Create an [`OpenOrdersAccount`](crate::state::OpenOrdersAccount).'], + accounts: [ + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'owner', + isMut: false, + isSigner: true, + }, + { + name: 'delegateAccount', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'openOrdersIndexer', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'name', + type: 'string', + }, + ], + }, + { + name: 'closeOpenOrdersAccount', + docs: ['Close an [`OpenOrdersAccount`](crate::state::OpenOrdersAccount).'], + accounts: [ + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'owner', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersIndexer', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'solDestination', + isMut: true, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'placeOrder', + docs: [ + 'Place an order.', + '', + 'Different types of orders have different effects on the order book,', + 'as described in [`PlaceOrderType`](crate::state::PlaceOrderType).', + '', + '`price_lots` refers to the price in lots: the number of quote lots', + 'per base lot. It is ignored for `PlaceOrderType::Market` orders.', + '', + '`expiry_timestamp` is a unix timestamp for when this order should', + 'expire. If 0 is passed in, the order will never expire. If the time', + 'is in the past, the instruction is skipped. Timestamps in the future', + 'are reduced to now + 65,535s.', + '', + '`limit` determines the maximum number of orders from the book to fill,', + 'and can be used to limit CU spent. When the limit is reached, processing', + 'stops and the instruction succeeds.', + ], + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAdmin', + isMut: false, + isSigner: true, + isOptional: true, + }, + { + name: 'userTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'marketVault', + isMut: true, + isSigner: false, + }, + { + name: 'oracleA', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'oracleB', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'args', + type: { + defined: 'PlaceOrderArgs', + }, + }, + ], + returns: { + option: 'u128', + }, + }, + { + name: 'editOrder', + docs: ['Edit an order.'], + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAdmin', + isMut: false, + isSigner: true, + isOptional: true, + }, + { + name: 'userTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'marketVault', + isMut: true, + isSigner: false, + }, + { + name: 'oracleA', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'oracleB', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'clientOrderId', + type: 'u64', + }, + { + name: 'expectedCancelSize', + type: 'i64', + }, + { + name: 'placeOrder', + type: { + defined: 'PlaceOrderArgs', + }, + }, + ], + returns: { + option: 'u128', + }, + }, + { + name: 'editOrderPegged', + docs: ['Edit an order pegged.'], + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAdmin', + isMut: false, + isSigner: true, + isOptional: true, + }, + { + name: 'userTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'marketVault', + isMut: true, + isSigner: false, + }, + { + name: 'oracleA', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'oracleB', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'clientOrderId', + type: 'u64', + }, + { + name: 'expectedCancelSize', + type: 'i64', + }, + { + name: 'placeOrder', + type: { + defined: 'PlaceOrderPeggedArgs', + }, + }, + ], + returns: { + option: 'u128', + }, + }, + { + name: 'cancelAndPlaceOrders', + docs: ['Cancel orders and place multiple orders.'], + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAdmin', + isMut: false, + isSigner: true, + isOptional: true, + }, + { + name: 'userQuoteAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userBaseAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'marketBaseVault', + isMut: true, + isSigner: false, + }, + { + name: 'oracleA', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'oracleB', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'cancelClientOrdersIds', + type: { + vec: 'u64', + }, + }, + { + name: 'placeOrders', + type: { + vec: { + defined: 'PlaceOrderArgs', + }, + }, + }, + ], + returns: { + vec: { + option: 'u128', + }, + }, + }, + { + name: 'placeOrderPegged', + docs: ['Place an oracle-peg order.'], + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAdmin', + isMut: false, + isSigner: true, + isOptional: true, + }, + { + name: 'userTokenAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'marketVault', + isMut: true, + isSigner: false, + }, + { + name: 'oracleA', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'oracleB', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'args', + type: { + defined: 'PlaceOrderPeggedArgs', + }, + }, + ], + returns: { + option: 'u128', + }, + }, + { + name: 'placeTakeOrder', + docs: [ + 'Place an order that shall take existing liquidity off of the book, not', + 'add a new order off the book.', + '', + 'This type of order allows for instant token settlement for the taker.', + ], + accounts: [ + { + name: 'signer', + isMut: true, + isSigner: true, + }, + { + name: 'penaltyPayer', + isMut: true, + isSigner: true, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'marketAuthority', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + { + name: 'marketBaseVault', + isMut: true, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + { + name: 'userBaseAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userQuoteAccount', + isMut: true, + isSigner: false, + }, + { + name: 'referrerAccount', + isMut: true, + isSigner: false, + isOptional: true, + }, + { + name: 'oracleA', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'oracleB', + isMut: false, + isSigner: false, + isOptional: true, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + { + name: 'openOrdersAdmin', + isMut: false, + isSigner: true, + isOptional: true, + }, + ], + args: [ + { + name: 'args', + type: { + defined: 'PlaceTakeOrderArgs', + }, + }, + ], + }, + { + name: 'consumeEvents', + docs: [ + 'Process up to `limit` [events](crate::state::AnyEvent).', + '', + "When a user places a 'take' order, they do not know beforehand which", + "market maker will have placed the 'make' order that they get executed", + "against. This prevents them from passing in a market maker's", + '[`OpenOrdersAccount`](crate::state::OpenOrdersAccount), which is needed', + 'to credit/debit the relevant tokens to/from the maker. As such, Openbook', + "uses a 'crank' system, where `place_order` only emits events, and", + '`consume_events` handles token settlement.', + '', + 'Currently, there are two types of events: [`FillEvent`](crate::state::FillEvent)s', + 'and [`OutEvent`](crate::state::OutEvent)s.', + '', + 'A `FillEvent` is emitted when an order is filled, and it is handled by', + 'debiting whatever the taker is selling from the taker and crediting', + 'it to the maker, and debiting whatever the taker is buying from the', + 'maker and crediting it to the taker. Note that *no tokens are moved*,', + "these are just debits and credits to each party's [`Position`](crate::state::Position).", + '', + 'An `OutEvent` is emitted when a limit order needs to be removed from', + 'the book during a `place_order` invocation, and it is handled by', + 'crediting whatever the maker would have sold (quote token in a bid,', + 'base token in an ask) back to the maker.', + ], + accounts: [ + { + name: 'consumeEventsAdmin', + isMut: false, + isSigner: true, + isOptional: true, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + ], + args: [ + { + name: 'limit', + type: 'u64', + }, + ], + }, + { + name: 'consumeGivenEvents', + docs: ['Process the [events](crate::state::AnyEvent) at the given positions.'], + accounts: [ + { + name: 'consumeEventsAdmin', + isMut: false, + isSigner: true, + isOptional: true, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'eventHeap', + isMut: true, + isSigner: false, + }, + ], + args: [ + { + name: 'slots', + type: { + vec: 'u64', + }, + }, + ], + }, + { + name: 'cancelOrder', + docs: [ + 'Cancel an order by its `order_id`.', + '', + "Note that this doesn't emit an [`OutEvent`](crate::state::OutEvent) because a", + 'maker knows that they will be passing in their own [`OpenOrdersAccount`](crate::state::OpenOrdersAccount).', + ], + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + ], + args: [ + { + name: 'orderId', + type: 'u128', + }, + ], + }, + { + name: 'cancelOrderByClientOrderId', + docs: [ + 'Cancel an order by its `client_order_id`.', + '', + "Note that this doesn't emit an [`OutEvent`](crate::state::OutEvent) because a", + 'maker knows that they will be passing in their own [`OpenOrdersAccount`](crate::state::OpenOrdersAccount).', + ], + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + ], + args: [ + { + name: 'clientOrderId', + type: 'u64', + }, + ], + returns: 'i64', + }, + { + name: 'cancelAllOrders', + docs: ['Cancel up to `limit` orders, optionally filtering by side'], + accounts: [ + { + name: 'signer', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + ], + args: [ + { + name: 'sideOption', + type: { + option: { + defined: 'Side', + }, + }, + }, + { + name: 'limit', + type: 'u8', + }, + ], + }, + { + name: 'deposit', + docs: [ + "Deposit a certain amount of `base` and `quote` lamports into one's", + '[`Position`](crate::state::Position).', + '', + 'Makers might wish to `deposit`, rather than have actual tokens moved for', + 'each trade, in order to reduce CUs.', + ], + accounts: [ + { + name: 'owner', + isMut: false, + isSigner: true, + }, + { + name: 'userBaseAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userQuoteAccount', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'marketBaseVault', + isMut: true, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'baseAmount', + type: 'u64', + }, + { + name: 'quoteAmount', + type: 'u64', + }, + ], + }, + { + name: 'refill', + docs: [ + 'Refill a certain amount of `base` and `quote` lamports. The amount being passed is the', + 'total lamports that the [`Position`](crate::state::Position) will have.', + '', + 'Makers might wish to `refill`, rather than have actual tokens moved for', + 'each trade, in order to reduce CUs.', + ], + accounts: [ + { + name: 'owner', + isMut: false, + isSigner: true, + }, + { + name: 'userBaseAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userQuoteAccount', + isMut: true, + isSigner: false, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'marketBaseVault', + isMut: true, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'baseAmount', + type: 'u64', + }, + { + name: 'quoteAmount', + type: 'u64', + }, + ], + }, + { + name: 'settleFunds', + docs: ['Withdraw any available tokens.'], + accounts: [ + { + name: 'owner', + isMut: true, + isSigner: true, + }, + { + name: 'penaltyPayer', + isMut: true, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'marketAuthority', + isMut: false, + isSigner: false, + }, + { + name: 'marketBaseVault', + isMut: true, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'userBaseAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userQuoteAccount', + isMut: true, + isSigner: false, + }, + { + name: 'referrerAccount', + isMut: true, + isSigner: false, + isOptional: true, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'settleFundsExpired', + docs: [ + 'Withdraw any available tokens when the market is expired (only', + '[`close_market_admin`](crate::state::Market::close_market_admin)).', + ], + accounts: [ + { + name: 'closeMarketAdmin', + isMut: false, + isSigner: true, + }, + { + name: 'owner', + isMut: true, + isSigner: true, + }, + { + name: 'penaltyPayer', + isMut: true, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'marketAuthority', + isMut: false, + isSigner: false, + }, + { + name: 'marketBaseVault', + isMut: true, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'userBaseAccount', + isMut: true, + isSigner: false, + }, + { + name: 'userQuoteAccount', + isMut: true, + isSigner: false, + }, + { + name: 'referrerAccount', + isMut: true, + isSigner: false, + isOptional: true, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'sweepFees', + docs: ["Sweep fees, as a [`Market`](crate::state::Market)'s admin."], + accounts: [ + { + name: 'collectFeeAdmin', + isMut: false, + isSigner: true, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + { + name: 'marketAuthority', + isMut: false, + isSigner: false, + }, + { + name: 'marketQuoteVault', + isMut: true, + isSigner: false, + }, + { + name: 'tokenReceiverAccount', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'setDelegate', + docs: [ + 'Update the [`delegate`](crate::state::OpenOrdersAccount::delegate) of an open orders account.', + ], + accounts: [ + { + name: 'owner', + isMut: true, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'delegateAccount', + isMut: false, + isSigner: false, + isOptional: true, + }, + ], + args: [], + }, + { + name: 'setMarketExpired', + docs: [ + 'Set market to expired before pruning orders and closing the market (only', + '[`close_market_admin`](crate::state::Market::close_market_admin)).', + ], + accounts: [ + { + name: 'closeMarketAdmin', + isMut: false, + isSigner: true, + }, + { + name: 'market', + isMut: true, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'pruneOrders', + docs: [ + 'Remove orders from the book when the market is expired (only', + '[`close_market_admin`](crate::state::Market::close_market_admin)).', + ], + accounts: [ + { + name: 'closeMarketAdmin', + isMut: false, + isSigner: true, + }, + { + name: 'openOrdersAccount', + isMut: true, + isSigner: false, + }, + { + name: 'market', + isMut: false, + isSigner: false, + }, + { + name: 'bids', + isMut: true, + isSigner: false, + }, + { + name: 'asks', + isMut: true, + isSigner: false, + }, + ], + args: [ + { + name: 'limit', + type: 'u8', + }, + ], + }, + { + name: 'stubOracleCreate', + accounts: [ + { + name: 'payer', + isMut: true, + isSigner: true, + }, + { + name: 'owner', + isMut: false, + isSigner: true, + }, + { + name: 'oracle', + isMut: true, + isSigner: false, + }, + { + name: 'mint', + isMut: false, + isSigner: false, + }, + { + name: 'systemProgram', + isMut: false, + isSigner: false, + }, + ], + args: [ + { + name: 'price', + type: 'f64', + }, + ], + }, + { + name: 'stubOracleClose', + accounts: [ + { + name: 'owner', + isMut: false, + isSigner: true, + }, + { + name: 'oracle', + isMut: true, + isSigner: false, + }, + { + name: 'solDestination', + isMut: true, + isSigner: false, + }, + { + name: 'tokenProgram', + isMut: false, + isSigner: false, + }, + ], + args: [], + }, + { + name: 'stubOracleSet', + accounts: [ + { + name: 'owner', + isMut: false, + isSigner: true, + }, + { + name: 'oracle', + isMut: true, + isSigner: false, + }, + ], + args: [ + { + name: 'price', + type: 'f64', + }, + ], + }, + ], + accounts: [ + { + name: 'market', + type: { + kind: 'struct', + fields: [ + { + name: 'bump', + docs: ['PDA bump'], + type: 'u8', + }, + { + name: 'baseDecimals', + docs: [ + 'Number of decimals used for the base token.', + '', + "Used to convert the oracle's price into a native/native price.", + ], + type: 'u8', + }, + { + name: 'quoteDecimals', + type: 'u8', + }, + { + name: 'padding1', + type: { + array: ['u8', 5], + }, + }, + { + name: 'marketAuthority', + type: 'publicKey', + }, + { + name: 'timeExpiry', + docs: ['No expiry = 0. Market will expire and no trading allowed after time_expiry'], + type: 'i64', + }, + { + name: 'collectFeeAdmin', + docs: ['Admin who can collect fees from the market'], + type: 'publicKey', + }, + { + name: 'openOrdersAdmin', + docs: ['Admin who must sign off on all order creations'], + type: { + defined: 'NonZeroPubkeyOption', + }, + }, + { + name: 'consumeEventsAdmin', + docs: ['Admin who must sign off on all event consumptions'], + type: { + defined: 'NonZeroPubkeyOption', + }, + }, + { + name: 'closeMarketAdmin', + docs: ['Admin who can set market expired, prune orders and close the market'], + type: { + defined: 'NonZeroPubkeyOption', + }, + }, + { + name: 'name', + docs: ['Name. Trailing zero bytes are ignored.'], + type: { + array: ['u8', 16], + }, + }, + { + name: 'bids', + docs: ['Address of the BookSide account for bids'], + type: 'publicKey', + }, + { + name: 'asks', + docs: ['Address of the BookSide account for asks'], + type: 'publicKey', + }, + { + name: 'eventHeap', + docs: ['Address of the EventHeap account'], + type: 'publicKey', + }, + { + name: 'oracleA', + docs: ['Oracles account address'], + type: { + defined: 'NonZeroPubkeyOption', + }, + }, + { + name: 'oracleB', + type: { + defined: 'NonZeroPubkeyOption', + }, + }, + { + name: 'oracleConfig', + docs: ['Oracle configuration'], + type: { + defined: 'OracleConfig', + }, + }, + { + name: 'quoteLotSize', + docs: [ + 'Number of quote native in a quote lot. Must be a power of 10.', + '', + 'Primarily useful for increasing the tick size on the market: A lot price', + 'of 1 becomes a native price of quote_lot_size/base_lot_size becomes a', + 'ui price of quote_lot_size*base_decimals/base_lot_size/quote_decimals.', + ], + type: 'i64', + }, + { + name: 'baseLotSize', + docs: [ + 'Number of base native in a base lot. Must be a power of 10.', + '', + 'Example: If base decimals for the underlying asset is 6, base lot size', + 'is 100 and and base position lots is 10_000 then base position native is', + '1_000_000 and base position ui is 1.', + ], + type: 'i64', + }, + { + name: 'seqNum', + docs: ['Total number of orders seen'], + type: 'u64', + }, + { + name: 'registrationTime', + docs: ['Timestamp in seconds that the market was registered at.'], + type: 'i64', + }, + { + name: 'makerFee', + docs: [ + 'Fees', + '', + 'Fee (in 10^-6) when matching maker orders.', + 'maker_fee < 0 it means some of the taker_fees goes to the maker', + 'maker_fee > 0, it means no taker_fee to the maker, and maker fee goes to the referral', + ], + type: 'i64', + }, + { + name: 'takerFee', + docs: ['Fee (in 10^-6) for taker orders, always >= 0.'], + type: 'i64', + }, + { + name: 'feesAccrued', + docs: ['Total fees accrued in native quote'], + type: 'u128', + }, + { + name: 'feesToReferrers', + docs: ['Total fees settled in native quote'], + type: 'u128', + }, + { + name: 'referrerRebatesAccrued', + docs: ['Referrer rebates to be distributed'], + type: 'u64', + }, + { + name: 'feesAvailable', + docs: ['Fees generated and available to withdraw via sweep_fees'], + type: 'u64', + }, + { + name: 'makerVolume', + docs: ['Cumulative maker volume (same as taker volume) in quote native units'], + type: 'u128', + }, + { + name: 'takerVolumeWoOo', + docs: ['Cumulative taker volume in quote native units due to place take orders'], + type: 'u128', + }, + { + name: 'baseMint', + type: 'publicKey', + }, + { + name: 'quoteMint', + type: 'publicKey', + }, + { + name: 'marketBaseVault', + type: 'publicKey', + }, + { + name: 'baseDepositTotal', + type: 'u64', + }, + { + name: 'marketQuoteVault', + type: 'publicKey', + }, + { + name: 'quoteDepositTotal', + type: 'u64', + }, + { + name: 'reserved', + type: { + array: ['u8', 128], + }, + }, + ], + }, + }, + { + name: 'openOrdersAccount', + type: { + kind: 'struct', + fields: [ + { + name: 'owner', + type: 'publicKey', + }, + { + name: 'market', + type: 'publicKey', + }, + { + name: 'name', + type: { + array: ['u8', 32], + }, + }, + { + name: 'delegate', + type: { + defined: 'NonZeroPubkeyOption', + }, + }, + { + name: 'accountNum', + type: 'u32', + }, + { + name: 'bump', + type: 'u8', + }, + { + name: 'padding', + type: { + array: ['u8', 3], + }, + }, + { + name: 'position', + type: { + defined: 'Position', + }, + }, + { + name: 'openOrders', + type: { + array: [ + { + defined: 'OpenOrder', + }, + 24, + ], + }, + }, + ], + }, + }, + { + name: 'openOrdersIndexer', + type: { + kind: 'struct', + fields: [ + { + name: 'bump', + type: 'u8', + }, + { + name: 'createdCounter', + type: 'u32', + }, + { + name: 'addresses', + type: { + vec: 'publicKey', + }, + }, + ], + }, + }, + { + name: 'stubOracle', + type: { + kind: 'struct', + fields: [ + { + name: 'owner', + type: 'publicKey', + }, + { + name: 'mint', + type: 'publicKey', + }, + { + name: 'price', + type: 'f64', + }, + { + name: 'lastUpdateTs', + type: 'i64', + }, + { + name: 'lastUpdateSlot', + type: 'u64', + }, + { + name: 'deviation', + type: 'f64', + }, + { + name: 'reserved', + type: { + array: ['u8', 104], + }, + }, + ], + }, + }, + { + name: 'bookSide', + type: { + kind: 'struct', + fields: [ + { + name: 'roots', + type: { + array: [ + { + defined: 'OrderTreeRoot', + }, + 2, + ], + }, + }, + { + name: 'reservedRoots', + type: { + array: [ + { + defined: 'OrderTreeRoot', + }, + 4, + ], + }, + }, + { + name: 'reserved', + type: { + array: ['u8', 256], + }, + }, + { + name: 'nodes', + type: { + defined: 'OrderTreeNodes', + }, + }, + ], + }, + }, + { + name: 'eventHeap', + docs: [ + 'Container for the different EventTypes.', + '', + 'Events are stored in a fixed-array of nodes. Free nodes are connected by a single-linked list', + 'starting at free_head while used nodes form a circular doubly-linked list starting at', + 'used_head.', + ], + type: { + kind: 'struct', + fields: [ + { + name: 'header', + type: { + defined: 'EventHeapHeader', + }, + }, + { + name: 'nodes', + type: { + array: [ + { + defined: 'EventNode', + }, + 600, + ], + }, + }, + { + name: 'reserved', + type: { + array: ['u8', 64], + }, + }, + ], + }, + }, + ], + types: [ + { + name: 'NonZeroPubkeyOption', + docs: ['Like `Option`, but implemented for `Pubkey` to be used with `zero_copy`'], + type: { + kind: 'struct', + fields: [ + { + name: 'key', + type: 'publicKey', + }, + ], + }, + }, + { + name: 'Position', + type: { + kind: 'struct', + fields: [ + { + name: 'bidsBaseLots', + docs: ['Base lots in open bids'], + type: 'i64', + }, + { + name: 'asksBaseLots', + docs: ['Base lots in open asks'], + type: 'i64', + }, + { + name: 'baseFreeNative', + type: 'u64', + }, + { + name: 'quoteFreeNative', + type: 'u64', + }, + { + name: 'lockedMakerFees', + type: 'u64', + }, + { + name: 'referrerRebatesAvailable', + type: 'u64', + }, + { + name: 'penaltyHeapCount', + docs: [ + 'Count of ixs when events are added to the heap', + 'To avoid this, send remaining accounts in order to process the events', + ], + type: 'u64', + }, + { + name: 'makerVolume', + docs: ['Cumulative maker volume in quote native units (display only)'], + type: 'u128', + }, + { + name: 'takerVolume', + docs: ['Cumulative taker volume in quote native units (display only)'], + type: 'u128', + }, + { + name: 'reserved', + type: { + array: ['u8', 72], + }, + }, + ], + }, + }, + { + name: 'OpenOrder', + type: { + kind: 'struct', + fields: [ + { + name: 'id', + type: 'u128', + }, + { + name: 'clientId', + type: 'u64', + }, + { + name: 'lockedPrice', + docs: ["Price at which user's assets were locked"], + type: 'i64', + }, + { + name: 'isFree', + type: 'u8', + }, + { + name: 'sideAndTree', + type: 'u8', + }, + { + name: 'padding', + type: { + array: ['u8', 6], + }, + }, + ], + }, + }, + { + name: 'OracleConfig', + type: { + kind: 'struct', + fields: [ + { + name: 'confFilter', + type: 'f64', + }, + { + name: 'maxStalenessSlots', + type: 'i64', + }, + { + name: 'reserved', + type: { + array: ['u8', 72], + }, + }, + ], + }, + }, + { + name: 'OracleConfigParams', + type: { + kind: 'struct', + fields: [ + { + name: 'confFilter', + type: 'f32', + }, + { + name: 'maxStalenessSlots', + type: { + option: 'u32', + }, + }, + ], + }, + }, + { + name: 'EventHeapHeader', + type: { + kind: 'struct', + fields: [ + { + name: 'freeHead', + type: 'u16', + }, + { + name: 'usedHead', + type: 'u16', + }, + { + name: 'count', + type: 'u16', + }, + { + name: 'padd', + type: 'u16', + }, + { + name: 'seqNum', + type: 'u64', + }, + ], + }, + }, + { + name: 'EventNode', + type: { + kind: 'struct', + fields: [ + { + name: 'next', + type: 'u16', + }, + { + name: 'prev', + type: 'u16', + }, + { + name: 'pad', + type: { + array: ['u8', 4], + }, + }, + { + name: 'event', + type: { + defined: 'AnyEvent', + }, + }, + ], + }, + }, + { + name: 'AnyEvent', + type: { + kind: 'struct', + fields: [ + { + name: 'eventType', + type: 'u8', + }, + { + name: 'padding', + type: { + array: ['u8', 143], + }, + }, + ], + }, + }, + { + name: 'FillEvent', + type: { + kind: 'struct', + fields: [ + { + name: 'eventType', + type: 'u8', + }, + { + name: 'takerSide', + type: 'u8', + }, + { + name: 'makerOut', + type: 'u8', + }, + { + name: 'makerSlot', + type: 'u8', + }, + { + name: 'padding', + type: { + array: ['u8', 4], + }, + }, + { + name: 'timestamp', + type: 'u64', + }, + { + name: 'seqNum', + type: 'u64', + }, + { + name: 'maker', + type: 'publicKey', + }, + { + name: 'makerTimestamp', + type: 'u64', + }, + { + name: 'taker', + type: 'publicKey', + }, + { + name: 'takerClientOrderId', + type: 'u64', + }, + { + name: 'price', + type: 'i64', + }, + { + name: 'pegLimit', + type: 'i64', + }, + { + name: 'quantity', + type: 'i64', + }, + { + name: 'makerClientOrderId', + type: 'u64', + }, + { + name: 'reserved', + type: { + array: ['u8', 8], + }, + }, + ], + }, + }, + { + name: 'OutEvent', + type: { + kind: 'struct', + fields: [ + { + name: 'eventType', + type: 'u8', + }, + { + name: 'side', + type: 'u8', + }, + { + name: 'ownerSlot', + type: 'u8', + }, + { + name: 'padding0', + type: { + array: ['u8', 5], + }, + }, + { + name: 'timestamp', + type: 'u64', + }, + { + name: 'seqNum', + type: 'u64', + }, + { + name: 'owner', + type: 'publicKey', + }, + { + name: 'quantity', + type: 'i64', + }, + { + name: 'padding1', + type: { + array: ['u8', 80], + }, + }, + ], + }, + }, + { + name: 'InnerNode', + docs: [ + 'InnerNodes and LeafNodes compose the binary tree of orders.', + '', + 'Each InnerNode has exactly two children, which are either InnerNodes themselves,', + 'or LeafNodes. The children share the top `prefix_len` bits of `key`. The left', + 'child has a 0 in the next bit, and the right a 1.', + ], + type: { + kind: 'struct', + fields: [ + { + name: 'tag', + type: 'u8', + }, + { + name: 'padding', + type: { + array: ['u8', 3], + }, + }, + { + name: 'prefixLen', + docs: [ + 'number of highest `key` bits that all children share', + "e.g. if it's 2, the two highest bits of `key` will be the same on all children", + ], + type: 'u32', + }, + { + name: 'key', + docs: ['only the top `prefix_len` bits of `key` are relevant'], + type: 'u128', + }, + { + name: 'children', + docs: ['indexes into `BookSide::nodes`'], + type: { + array: ['u32', 2], + }, + }, + { + name: 'childEarliestExpiry', + docs: [ + 'The earliest expiry timestamp for the left and right subtrees.', + '', + 'Needed to be able to find and remove expired orders without having to', + 'iterate through the whole bookside.', + ], + type: { + array: ['u64', 2], + }, + }, + { + name: 'reserved', + type: { + array: ['u8', 40], + }, + }, + ], + }, + }, + { + name: 'LeafNode', + docs: ['LeafNodes represent an order in the binary tree'], + type: { + kind: 'struct', + fields: [ + { + name: 'tag', + docs: ['NodeTag'], + type: 'u8', + }, + { + name: 'ownerSlot', + docs: ["Index into the owning OpenOrdersAccount's OpenOrders"], + type: 'u8', + }, + { + name: 'timeInForce', + docs: [ + 'Time in seconds after `timestamp` at which the order expires.', + 'A value of 0 means no expiry.', + ], + type: 'u16', + }, + { + name: 'padding', + type: { + array: ['u8', 4], + }, + }, + { + name: 'key', + docs: ['The binary tree key, see new_node_key()'], + type: 'u128', + }, + { + name: 'owner', + docs: ['Address of the owning OpenOrdersAccount'], + type: 'publicKey', + }, + { + name: 'quantity', + docs: ['Number of base lots to buy or sell, always >=1'], + type: 'i64', + }, + { + name: 'timestamp', + docs: ['The time the order was placed'], + type: 'u64', + }, + { + name: 'pegLimit', + docs: [ + 'If the effective price of an oracle pegged order exceeds this limit,', + 'it will be considered invalid and may be removed.', + '', + 'Only applicable in the oracle_pegged OrderTree', + ], + type: 'i64', + }, + { + name: 'clientOrderId', + docs: ['User defined id for this order, used in FillEvents'], + type: 'u64', + }, + ], + }, + }, + { + name: 'AnyNode', + type: { + kind: 'struct', + fields: [ + { + name: 'tag', + type: 'u8', + }, + { + name: 'data', + type: { + array: ['u8', 87], + }, + }, + ], + }, + }, + { + name: 'OrderTreeRoot', + type: { + kind: 'struct', + fields: [ + { + name: 'maybeNode', + type: 'u32', + }, + { + name: 'leafCount', + type: 'u32', + }, + ], + }, + }, + { + name: 'OrderTreeNodes', + docs: [ + 'A binary tree on AnyNode::key()', + '', + 'The key encodes the price in the top 64 bits.', + ], + type: { + kind: 'struct', + fields: [ + { + name: 'orderTreeType', + type: 'u8', + }, + { + name: 'padding', + type: { + array: ['u8', 3], + }, + }, + { + name: 'bumpIndex', + type: 'u32', + }, + { + name: 'freeListLen', + type: 'u32', + }, + { + name: 'freeListHead', + type: 'u32', + }, + { + name: 'reserved', + type: { + array: ['u8', 512], + }, + }, + { + name: 'nodes', + type: { + array: [ + { + defined: 'AnyNode', + }, + 1024, + ], + }, + }, + ], + }, + }, + { + name: 'I80F48', + docs: [ + 'Nothing in Rust shall use these types. They only exist so that the Anchor IDL', + 'knows about them and typescript can deserialize it.', + ], + type: { + kind: 'struct', + fields: [ + { + name: 'val', + type: 'i128', + }, + ], + }, + }, + { + name: 'PlaceOrderArgs', + type: { + kind: 'struct', + fields: [ + { + name: 'side', + type: { + defined: 'Side', + }, + }, + { + name: 'priceLots', + type: 'i64', + }, + { + name: 'maxBaseLots', + type: 'i64', + }, + { + name: 'maxQuoteLotsIncludingFees', + type: 'i64', + }, + { + name: 'clientOrderId', + type: 'u64', + }, + { + name: 'orderType', + type: { + defined: 'PlaceOrderType', + }, + }, + { + name: 'expiryTimestamp', + type: 'u64', + }, + { + name: 'selfTradeBehavior', + type: { + defined: 'SelfTradeBehavior', + }, + }, + { + name: 'limit', + type: 'u8', + }, + ], + }, + }, + { + name: 'PlaceOrderPeggedArgs', + type: { + kind: 'struct', + fields: [ + { + name: 'side', + type: { + defined: 'Side', + }, + }, + { + name: 'priceOffsetLots', + type: 'i64', + }, + { + name: 'pegLimit', + type: 'i64', + }, + { + name: 'maxBaseLots', + type: 'i64', + }, + { + name: 'maxQuoteLotsIncludingFees', + type: 'i64', + }, + { + name: 'clientOrderId', + type: 'u64', + }, + { + name: 'orderType', + type: { + defined: 'PlaceOrderType', + }, + }, + { + name: 'expiryTimestamp', + type: 'u64', + }, + { + name: 'selfTradeBehavior', + type: { + defined: 'SelfTradeBehavior', + }, + }, + { + name: 'limit', + type: 'u8', + }, + ], + }, + }, + { + name: 'PlaceTakeOrderArgs', + type: { + kind: 'struct', + fields: [ + { + name: 'side', + type: { + defined: 'Side', + }, + }, + { + name: 'priceLots', + type: 'i64', + }, + { + name: 'maxBaseLots', + type: 'i64', + }, + { + name: 'maxQuoteLotsIncludingFees', + type: 'i64', + }, + { + name: 'orderType', + type: { + defined: 'PlaceOrderType', + }, + }, + { + name: 'limit', + type: 'u8', + }, + ], + }, + }, + { + name: 'OracleType', + type: { + kind: 'enum', + variants: [ + { + name: 'Pyth', + }, + { + name: 'Stub', + }, + { + name: 'SwitchboardV1', + }, + { + name: 'SwitchboardV2', + }, + { + name: 'RaydiumCLMM', + }, + ], + }, + }, + { + name: 'OrderState', + type: { + kind: 'enum', + variants: [ + { + name: 'Valid', + }, + { + name: 'Invalid', + }, + { + name: 'Skipped', + }, + ], + }, + }, + { + name: 'BookSideOrderTree', + type: { + kind: 'enum', + variants: [ + { + name: 'Fixed', + }, + { + name: 'OraclePegged', + }, + ], + }, + }, + { + name: 'EventType', + type: { + kind: 'enum', + variants: [ + { + name: 'Fill', + }, + { + name: 'Out', + }, + ], + }, + }, + { + name: 'NodeTag', + type: { + kind: 'enum', + variants: [ + { + name: 'Uninitialized', + }, + { + name: 'InnerNode', + }, + { + name: 'LeafNode', + }, + { + name: 'FreeNode', + }, + { + name: 'LastFreeNode', + }, + ], + }, + }, + { + name: 'PlaceOrderType', + type: { + kind: 'enum', + variants: [ + { + name: 'Limit', + }, + { + name: 'ImmediateOrCancel', + }, + { + name: 'PostOnly', + }, + { + name: 'Market', + }, + { + name: 'PostOnlySlide', + }, + ], + }, + }, + { + name: 'PostOrderType', + type: { + kind: 'enum', + variants: [ + { + name: 'Limit', + }, + { + name: 'PostOnly', + }, + { + name: 'PostOnlySlide', + }, + ], + }, + }, + { + name: 'SelfTradeBehavior', + docs: [ + 'Self trade behavior controls how taker orders interact with resting limit orders of the same account.', + 'This setting has no influence on placing a resting or oracle pegged limit order that does not match', + "immediately, instead it's the responsibility of the user to correctly configure his taker orders.", + ], + type: { + kind: 'enum', + variants: [ + { + name: 'DecrementTake', + }, + { + name: 'CancelProvide', + }, + { + name: 'AbortTransaction', + }, + ], + }, + }, + { + name: 'Side', + type: { + kind: 'enum', + variants: [ + { + name: 'Bid', + }, + { + name: 'Ask', + }, + ], + }, + }, + { + name: 'SideAndOrderTree', + docs: ["SideAndOrderTree is a storage optimization, so we don't need two bytes for the data"], + type: { + kind: 'enum', + variants: [ + { + name: 'BidFixed', + }, + { + name: 'AskFixed', + }, + { + name: 'BidOraclePegged', + }, + { + name: 'AskOraclePegged', + }, + ], + }, + }, + { + name: 'OrderParams', + type: { + kind: 'enum', + variants: [ + { + name: 'Market', + }, + { + name: 'ImmediateOrCancel', + fields: [ + { + name: 'price_lots', + type: 'i64', + }, + ], + }, + { + name: 'Fixed', + fields: [ + { + name: 'price_lots', + type: 'i64', + }, + { + name: 'order_type', + type: { + defined: 'PostOrderType', + }, + }, + ], + }, + { + name: 'OraclePegged', + fields: [ + { + name: 'price_offset_lots', + type: 'i64', + }, + { + name: 'order_type', + type: { + defined: 'PostOrderType', + }, + }, + { + name: 'peg_limit', + type: 'i64', + }, + ], + }, + ], + }, + }, + { + name: 'OrderTreeType', + type: { + kind: 'enum', + variants: [ + { + name: 'Bids', + }, + { + name: 'Asks', + }, + ], + }, + }, + ], + events: [ + { + name: 'DepositLog', + fields: [ + { + name: 'openOrdersAccount', + type: 'publicKey', + index: false, + }, + { + name: 'signer', + type: 'publicKey', + index: false, + }, + { + name: 'baseAmount', + type: 'u64', + index: false, + }, + { + name: 'quoteAmount', + type: 'u64', + index: false, + }, + ], + }, + { + name: 'FillLog', + fields: [ + { + name: 'market', + type: 'publicKey', + index: false, + }, + { + name: 'takerSide', + type: 'u8', + index: false, + }, + { + name: 'makerSlot', + type: 'u8', + index: false, + }, + { + name: 'makerOut', + type: 'bool', + index: false, + }, + { + name: 'timestamp', + type: 'u64', + index: false, + }, + { + name: 'seqNum', + type: 'u64', + index: false, + }, + { + name: 'maker', + type: 'publicKey', + index: false, + }, + { + name: 'makerClientOrderId', + type: 'u64', + index: false, + }, + { + name: 'makerFee', + type: 'i64', + index: false, + }, + { + name: 'makerTimestamp', + type: 'u64', + index: false, + }, + { + name: 'taker', + type: 'publicKey', + index: false, + }, + { + name: 'takerClientOrderId', + type: 'u64', + index: false, + }, + { + name: 'takerFee', + type: 'i64', + index: false, + }, + { + name: 'price', + type: 'i64', + index: false, + }, + { + name: 'quantity', + type: 'i64', + index: false, + }, + ], + }, + { + name: 'MarketMetaDataLog', + fields: [ + { + name: 'market', + type: 'publicKey', + index: false, + }, + { + name: 'name', + type: 'string', + index: false, + }, + { + name: 'baseMint', + type: 'publicKey', + index: false, + }, + { + name: 'quoteMint', + type: 'publicKey', + index: false, + }, + { + name: 'baseDecimals', + type: 'u8', + index: false, + }, + { + name: 'quoteDecimals', + type: 'u8', + index: false, + }, + { + name: 'baseLotSize', + type: 'i64', + index: false, + }, + { + name: 'quoteLotSize', + type: 'i64', + index: false, + }, + ], + }, + { + name: 'TotalOrderFillEvent', + fields: [ + { + name: 'side', + type: 'u8', + index: false, + }, + { + name: 'taker', + type: 'publicKey', + index: false, + }, + { + name: 'totalQuantityPaid', + type: 'u64', + index: false, + }, + { + name: 'totalQuantityReceived', + type: 'u64', + index: false, + }, + { + name: 'fees', + type: 'u64', + index: false, + }, + ], + }, + { + name: 'SetDelegateLog', + fields: [ + { + name: 'openOrdersAccount', + type: 'publicKey', + index: false, + }, + { + name: 'delegate', + type: { + option: 'publicKey', + }, + index: false, + }, + ], + }, + { + name: 'SettleFundsLog', + fields: [ + { + name: 'openOrdersAccount', + type: 'publicKey', + index: false, + }, + { + name: 'baseNative', + type: 'u64', + index: false, + }, + { + name: 'quoteNative', + type: 'u64', + index: false, + }, + { + name: 'referrerRebate', + type: 'u64', + index: false, + }, + { + name: 'referrer', + type: { + option: 'publicKey', + }, + index: false, + }, + ], + }, + { + name: 'SweepFeesLog', + fields: [ + { + name: 'market', + type: 'publicKey', + index: false, + }, + { + name: 'amount', + type: 'u64', + index: false, + }, + { + name: 'receiver', + type: 'publicKey', + index: false, + }, + ], + }, + { + name: 'OpenOrdersPositionLog', + fields: [ + { + name: 'owner', + type: 'publicKey', + index: false, + }, + { + name: 'openOrdersAccountNum', + type: 'u32', + index: false, + }, + { + name: 'market', + type: 'publicKey', + index: false, + }, + { + name: 'bidsBaseLots', + type: 'i64', + index: false, + }, + { + name: 'asksBaseLots', + type: 'i64', + index: false, + }, + { + name: 'baseFreeNative', + type: 'u64', + index: false, + }, + { + name: 'quoteFreeNative', + type: 'u64', + index: false, + }, + { + name: 'lockedMakerFees', + type: 'u64', + index: false, + }, + { + name: 'referrerRebatesAvailable', + type: 'u64', + index: false, + }, + { + name: 'makerVolume', + type: 'u128', + index: false, + }, + { + name: 'takerVolume', + type: 'u128', + index: false, + }, + ], + }, + ], + errors: [ + { + code: 6000, + name: 'SomeError', + msg: '', + }, + { + code: 6001, + name: 'InvalidInputNameLength', + msg: 'Name lenght above limit', + }, + { + code: 6002, + name: 'InvalidInputMarketExpired', + msg: 'Market cannot be created as expired', + }, + { + code: 6003, + name: 'InvalidInputMarketFees', + msg: 'Taker fees should be positive and if maker fees are negative, greater or equal to their abs value', + }, + { + code: 6004, + name: 'InvalidInputLots', + msg: 'Lots cannot be negative', + }, + { + code: 6005, + name: 'InvalidInputLotsSize', + msg: 'Lots size above market limits', + }, + { + code: 6006, + name: 'InvalidInputOrdersAmounts', + msg: 'Input amounts above limits', + }, + { + code: 6007, + name: 'InvalidInputCancelSize', + msg: 'Price lots should be greater than zero', + }, + { + code: 6008, + name: 'InvalidInputPriceLots', + msg: 'Expected cancel size should be greater than zero', + }, + { + code: 6009, + name: 'InvalidInputPegLimit', + msg: 'Peg limit should be greater than zero', + }, + { + code: 6010, + name: 'InvalidInputOrderType', + msg: 'The order type is invalid. A taker order must be Market or ImmediateOrCancel', + }, + { + code: 6011, + name: 'InvalidInputOrderId', + msg: 'Order id cannot be zero', + }, + { + code: 6012, + name: 'InvalidInputHeapSlots', + msg: 'Slot above heap limit', + }, + { + code: 6013, + name: 'InvalidOracleTypes', + msg: 'Cannot combine two oracles of different providers', + }, + { + code: 6014, + name: 'InvalidSecondOracle', + msg: 'Cannot configure secondary oracle without primary', + }, + { + code: 6015, + name: 'NoCloseMarketAdmin', + msg: 'This market does not have a `close_market_admin` and thus cannot be closed.', + }, + { + code: 6016, + name: 'InvalidCloseMarketAdmin', + msg: "The signer of this transaction is not this market's `close_market_admin`.", + }, + { + code: 6017, + name: 'InvalidOpenOrdersAdmin', + msg: 'The `open_orders_admin` required by this market to sign all instructions that creates orders is missing or is not valid', + }, + { + code: 6018, + name: 'InvalidConsumeEventsAdmin', + msg: 'The `consume_events_admin` required by this market to sign all instructions that consume events is missing or is not valid', + }, + { + code: 6019, + name: 'InvalidMarketVault', + msg: 'Provided `market_vault` is invalid', + }, + { + code: 6020, + name: 'IndexerActiveOO', + msg: 'Cannot be closed due to the existence of open orders accounts', + }, + { + code: 6021, + name: 'OraclePegInvalidOracleState', + msg: 'Cannot place a peg order due to invalid oracle state', + }, + { + code: 6022, + name: 'UnknownOracleType', + msg: 'oracle type cannot be determined', + }, + { + code: 6023, + name: 'OracleConfidence', + msg: 'an oracle does not reach the confidence threshold', + }, + { + code: 6024, + name: 'OracleStale', + msg: 'an oracle is stale', + }, + { + code: 6025, + name: 'OrderIdNotFound', + msg: 'Order id not found on the orderbook', + }, + { + code: 6026, + name: 'EventHeapContainsElements', + msg: "Event heap contains elements and market can't be closed", + }, + { + code: 6027, + name: 'InvalidOrderPostIOC', + msg: 'ImmediateOrCancel is not a PostOrderType', + }, + { + code: 6028, + name: 'InvalidOrderPostMarket', + msg: 'Market is not a PostOrderType', + }, + { + code: 6029, + name: 'WouldSelfTrade', + msg: 'would self trade', + }, + { + code: 6030, + name: 'MarketHasExpired', + msg: 'The Market has already expired.', + }, + { + code: 6031, + name: 'InvalidPriceLots', + msg: 'Price lots should be greater than zero', + }, + { + code: 6032, + name: 'InvalidOraclePrice', + msg: 'Oracle price above market limits', + }, + { + code: 6033, + name: 'MarketHasNotExpired', + msg: 'The Market has not expired yet.', + }, + { + code: 6034, + name: 'NoOwnerOrDelegate', + msg: 'No correct owner or delegate.', + }, + { + code: 6035, + name: 'NoOwner', + msg: 'No correct owner', + }, + { + code: 6036, + name: 'OpenOrdersFull', + msg: 'No free order index in open orders account', + }, + { + code: 6037, + name: 'BookContainsElements', + msg: 'Book contains elements', + }, + { + code: 6038, + name: 'OpenOrdersOrderNotFound', + msg: 'Could not find order in user account', + }, + { + code: 6039, + name: 'InvalidPostAmount', + msg: 'Amount to post above book limits', + }, + { + code: 6040, + name: 'DisabledOraclePeg', + msg: 'Oracle peg orders are not enabled for this market', + }, + { + code: 6041, + name: 'NonEmptyMarket', + msg: 'Cannot close a non-empty market', + }, + { + code: 6042, + name: 'NonEmptyOpenOrdersPosition', + msg: 'Cannot close a non-empty open orders account', + }, + ], +}; diff --git a/packages/futarchy-ts/lib/instructions/autocrat.ts b/packages/futarchy-ts/lib/instructions/autocrat.ts new file mode 100644 index 00000000..e9f3da92 --- /dev/null +++ b/packages/futarchy-ts/lib/instructions/autocrat.ts @@ -0,0 +1,48 @@ +import { BorshInstructionCoder, utils } from '@coral-xyz/anchor'; +import { PublicKey } from '@solana/web3.js'; +import { AUTOCRAT_VERSIONS } from '../constants'; +import { InstructionFieldTypes, InstructionSet } from '../types'; + +const defaultVersion = AUTOCRAT_VERSIONS[0]; +const coder = new BorshInstructionCoder(defaultVersion.idl); +// const program = new Program(AUTOCRAT_IDL, AUTOCRAT_PROGRAM_ID); +const dao = PublicKey.findProgramAddressSync( + [utils.bytes.utf8.encode('WWCACOTMICMIBMHAFTTWYGHMB')], + defaultVersion.programId, +)[0]; +const daoTreasury = PublicKey.findProgramAddressSync([dao.toBuffer()], defaultVersion.programId)[0]; +export const instructions: InstructionSet = { + name: 'Autocrat', + actions: [ + { + label: 'Update DAO', + fields: [ + { + type: InstructionFieldTypes.Number, + required: true, + label: 'Threshold', + description: + 'The difference threshold needed between PASS and FAIL market for a proposal to pass, in basis points', + }, + ], + instruction: async (params: any[]) => ({ + programId: defaultVersion.programId, + accounts: [ + { + pubkey: dao, + isSigner: true, + isWritable: true, + }, + { + pubkey: daoTreasury, + isSigner: true, + isWritable: false, + }, + ], + data: coder.encode('update_dao', { + passThresholdBps: params[0], + }), + }), + }, + ], +}; diff --git a/packages/futarchy-ts/lib/instructions/index.ts b/packages/futarchy-ts/lib/instructions/index.ts new file mode 100644 index 00000000..7447f1f2 --- /dev/null +++ b/packages/futarchy-ts/lib/instructions/index.ts @@ -0,0 +1,5 @@ +// import { instructions as autocrat } from './autocrat'; +// import { instructions as solana } from './solana'; +import { instructions as spl } from './spl'; + +export const instructionGroups = [spl]; diff --git a/packages/futarchy-ts/lib/instructions/solana.ts b/packages/futarchy-ts/lib/instructions/solana.ts new file mode 100644 index 00000000..79f4c18b --- /dev/null +++ b/packages/futarchy-ts/lib/instructions/solana.ts @@ -0,0 +1,46 @@ +import { utils } from '@coral-xyz/anchor'; +import { PublicKey, SystemProgram } from '@solana/web3.js'; +import { AUTOCRAT_VERSIONS } from '../constants'; +import { InstructionFieldTypes, InstructionSet } from '../types'; + +const defaultVersion = AUTOCRAT_VERSIONS[0]; +const dao = PublicKey.findProgramAddressSync( + [utils.bytes.utf8.encode('WWCACOTMICMIBMHAFTTWYGHMB')], + defaultVersion.programId, +)[0]; +const daoTreasury = PublicKey.findProgramAddressSync([dao.toBuffer()], defaultVersion.programId)[0]; +export const instructions: InstructionSet = { + name: 'Solana', + actions: [ + { + label: 'Transfer lamports', + fields: [ + { + type: InstructionFieldTypes.Key, + required: true, + label: 'Recipient', + description: 'The wallet that will receive the token', + }, + { + type: InstructionFieldTypes.BigNumber, + required: true, + label: 'Amount', + description: 'The amount of SOL to transfer', + }, + ], + instruction: async (params: any[]) => { + const ix = SystemProgram.transfer({ + fromPubkey: daoTreasury, + toPubkey: params[0], + lamports: params[1], + }); + + return { + programId: SystemProgram.programId, + accounts: ix.keys, + data: ix.data, + }; + }, + }, + ], +}; diff --git a/packages/futarchy-ts/lib/instructions/spl.ts b/packages/futarchy-ts/lib/instructions/spl.ts new file mode 100644 index 00000000..78c7feeb --- /dev/null +++ b/packages/futarchy-ts/lib/instructions/spl.ts @@ -0,0 +1,68 @@ +import { BN, utils } from '@coral-xyz/anchor'; +import { PublicKey } from '@solana/web3.js'; +import { + TOKEN_PROGRAM_ID, + createTransferCheckedInstruction, + getAssociatedTokenAddressSync, + getMint, +} from '@solana/spl-token'; +import { AUTOCRAT_VERSIONS } from '../constants'; +import { InstructionFieldTypes, InstructionSet } from '../types'; + +const defaultVersion = AUTOCRAT_VERSIONS[0]; +const dao = PublicKey.findProgramAddressSync( + [utils.bytes.utf8.encode('WWCACOTMICMIBMHAFTTWYGHMB')], + defaultVersion.programId, +)[0]; +const daoTreasury = PublicKey.findProgramAddressSync([dao.toBuffer()], defaultVersion.programId)[0]; +export const instructions: InstructionSet = { + name: 'SPL', + actions: [ + { + label: 'Transfer tokens', + fields: [ + { + type: InstructionFieldTypes.Key, + required: true, + label: 'Recipient', + description: + 'The wallet that will receive the token (not the token account) from the treasury', + }, + { + type: InstructionFieldTypes.Key, + required: true, + label: 'Token Mint', + description: 'The mint of the token to transfer from the treasury', + }, + { + type: InstructionFieldTypes.Number, + required: true, + label: 'Amount', + description: 'The amount of tokens to transfer', + }, + ], + instruction: async (params, options = {}) => { + if (!options?.connection) throw new Error('Connection not provided'); + + const recipient = new PublicKey(params[0]); + const mint = new PublicKey(params[1]); + const mintAccount = await getMint(options.connection, mint); + const amount = new BN(Number(params[2]) * 10 ** mintAccount.decimals); + const ix = createTransferCheckedInstruction( + getAssociatedTokenAddressSync(mint, daoTreasury, true), + mint, + getAssociatedTokenAddressSync(mint, recipient, true), + daoTreasury, + amount, + mintAccount.decimals, + ); + + return { + programId: TOKEN_PROGRAM_ID, + accounts: ix.keys, + data: ix.data, + }; + }, + }, + ], +}; diff --git a/packages/futarchy-ts/lib/openbook.ts b/packages/futarchy-ts/lib/openbook.ts new file mode 100644 index 00000000..26c7432d --- /dev/null +++ b/packages/futarchy-ts/lib/openbook.ts @@ -0,0 +1,355 @@ +import { Program, BN } from '@coral-xyz/anchor'; +import { OpenbookV2 } from '@openbook-dex/openbook-v2'; +import { + Keypair, + PublicKey, + Signer, + SystemProgram, + Transaction, + TransactionInstruction, +} from '@solana/web3.js'; +import numeral from 'numeral'; +import { getAssociatedTokenAddressSync } from '@solana/spl-token'; +import { + AnyNode, + BookSideAccount, + LeafNode, + Markets, + OpenOrdersAccountWithKey, + OracleConfigParams, + ProposalAccountWithKey, +} from './types'; +import { BASE_FORMAT, BN_0, NUMERAL_FORMAT, OPENBOOK_PROGRAM_ID } from './constants'; + +export type Order = { + price: number; + size: number; +}; + +const BooksideSpace = 90944 + 8; +const EventHeapSpace = 91280 + 8; + +export const createProgramAccount = async ( + program: Program, + authority: PublicKey, + size: number, +) => { + const lamports = await program.provider.connection.getMinimumBalanceForRentExemption(size); + const address = Keypair.generate(); + const tx = new Transaction().add( + SystemProgram.createAccount({ + fromPubkey: authority, + newAccountPubkey: address.publicKey, + lamports, + space: size, + programId: program.programId, + }), + ); + return { tx, signers: [address] }; +}; + +export const createOpenbookMarket = async ( + program: Program, + creator: PublicKey, + baseMint: PublicKey, + quoteMint: PublicKey, + name: string, + quoteLotSize: BN, + baseLotSize: BN, + makerFee: BN, + takerFee: BN, + timeExpiry: BN, + oracleA: PublicKey | null, + oracleB: PublicKey | null, + openOrdersAdmin: PublicKey | null, + consumeEventsAdmin: PublicKey | null, + closeMarketAdmin: PublicKey | null, + oracleConfigParams: OracleConfigParams = { confFilter: 0.1, maxStalenessSlots: 100 }, + market: Keypair = Keypair.generate(), + collectFeeAdmin?: PublicKey, +): Promise<{ signers: Signer[]; instructions: (Transaction | TransactionInstruction)[] }> => { + const bids = await createProgramAccount(program, creator, BooksideSpace); + const asks = await createProgramAccount(program, creator, BooksideSpace); + const eventHeap = await createProgramAccount(program, creator, EventHeapSpace); + const [marketAuthority] = PublicKey.findProgramAddressSync( + [Buffer.from('Market'), market.publicKey.toBuffer()], + program.programId, + ); + const baseVault = getAssociatedTokenAddressSync(baseMint, marketAuthority, true); + const quoteVault = getAssociatedTokenAddressSync(quoteMint, marketAuthority, true); + const [eventAuthority] = PublicKey.findProgramAddressSync( + [Buffer.from('__event_authority')], + program.programId, + ); + + return { + signers: [...bids.signers, ...asks.signers, ...eventHeap.signers, market], + instructions: [ + bids.tx, + asks.tx, + eventHeap.tx, + await program.methods + .createMarket( + name, + oracleConfigParams, + quoteLotSize, + baseLotSize, + makerFee, + takerFee, + timeExpiry, + ) + .accounts({ + market: market.publicKey, + marketAuthority, + bids: bids.signers[0].publicKey, + asks: asks.signers[0].publicKey, + eventHeap: eventHeap.signers[0].publicKey, + payer: creator, + marketBaseVault: baseVault, + marketQuoteVault: quoteVault, + baseMint, + quoteMint, + oracleA, + oracleB, + collectFeeAdmin: collectFeeAdmin != null ? collectFeeAdmin : creator, + openOrdersAdmin, + consumeEventsAdmin, + closeMarketAdmin, + eventAuthority, + program: program.programId, + }) + .instruction(), + ], + }; +}; + +export const findOpenOrdersIndexer = (owner: PublicKey): PublicKey => { + const [openOrdersIndexer] = PublicKey.findProgramAddressSync( + [Buffer.from('OpenOrdersIndexer'), owner.toBuffer()], + OPENBOOK_PROGRAM_ID, + ); + return openOrdersIndexer; +}; + +export const createOpenOrdersIndexerInstruction = async ( + program: Program, + openOrdersIndexer: PublicKey, + owner: PublicKey, +): Promise => + program.methods + .createOpenOrdersIndexer() + .accounts({ + openOrdersIndexer, + owner, + payer: owner, + }) + .instruction(); + +export const findOpenOrders = (accountIndex: BN, owner: PublicKey): PublicKey => { + const [openOrders] = PublicKey.findProgramAddressSync( + [Buffer.from('OpenOrders'), owner.toBuffer(), accountIndex.toArrayLike(Buffer, 'le', 4)], + OPENBOOK_PROGRAM_ID, + ); + return openOrders; +}; + +export const createOpenOrdersInstruction = async ( + program: Program, + market: PublicKey, + accountIndex: BN, + name: string, + owner: PublicKey, + openOrdersIndexer: PublicKey, +): Promise<[TransactionInstruction[], PublicKey]> => { + const ixs: TransactionInstruction[] = []; + + if (accountIndex.toNumber() === 0) { + throw Object.assign(new Error('accountIndex can not be 0'), { + code: 403, + }); + } + const openOrdersAccount = findOpenOrders(accountIndex, owner); + + ixs.push( + await program.methods + .createOpenOrdersAccount(name) + .accounts({ + openOrdersIndexer, + openOrdersAccount, + market, + owner, + delegateAccount: null, + }) + .instruction(), + ); + + return [ixs, openOrdersAccount]; +}; + +export function getLeafNodes(bookside: BookSideAccount, program: Program): LeafNode[] { + const leafNodesData = bookside.nodes.nodes.filter((x: AnyNode) => x.tag === 2); + return leafNodesData.map((e) => + program.coder.types.decode('LeafNode', Buffer.from([0, ...e.data])), + ); +} + +export function getParsedOrders(side: LeafNode[], isBidSide: boolean): Order[] { + if (side.length === 0) { + return []; + } + + const parsed = side + .map((e) => ({ + price: e.key.shrn(64).toNumber(), + size: e.quantity.toNumber(), + })) + .sort((a, b) => a.price - b.price); + + const sorted = isBidSide + ? parsed.sort((a, b) => b.price - a.price) + : parsed.sort((a, b) => a.price - b.price); + + // const deduped = new Map(); + // sorted.forEach((order) => { + // if (deduped.get(order.price) === undefined) { + // deduped.set(order.price, order.size); + // } else { + // deduped.set(order.price, deduped.get(order.price) + order.size); + // } + // }); + + return sorted; +} + +export const isPass = (order: OpenOrdersAccountWithKey, proposal?: ProposalAccountWithKey) => + proposal?.account.openbookPassMarket.equals(order.account.market)!!; + +export const isBid = (order: OpenOrdersAccountWithKey) => { + const isBidSide = order.account.position.bidsBaseLots.gt(order.account.position.asksBaseLots); + if (isBidSide) { + return true; + } + return false; +}; + +export const isPartiallyFilled = (order: OpenOrdersAccountWithKey): boolean => { + const orderPosition = order.account.position; + if (orderPosition.baseFreeNative > BN_0 || orderPosition.quoteFreeNative > BN_0) { + return true; + } + return false; +}; + +export const isEmptyOrder = (order: OpenOrdersAccountWithKey): boolean => + order.account.openOrders[0].isFree === 1; + +export const isClosableOrder = (order: OpenOrdersAccountWithKey): boolean => + order.account.position.asksBaseLots.eq(BN_0) && + order.account.position.bidsBaseLots.eq(BN_0) && + order.account.position.baseFreeNative.eq(BN_0) && + order.account.position.quoteFreeNative.eq(BN_0); + +export const isOpenOrder = (order: OpenOrdersAccountWithKey, markets: Markets): boolean => { + if (order.account.openOrders[0].isFree === 0) { + const passAsksFilter = markets.passAsks.filter( + (_order) => _order.owner.toString() === order.publicKey.toString(), + ); + const passBidsFilter = markets.passBids.filter( + (_order) => _order.owner.toString() === order.publicKey.toString(), + ); + const failAsksFilter = markets.failAsks.filter( + (_order) => _order.owner.toString() === order.publicKey.toString(), + ); + const failBidsFilter = markets.failBids.filter( + (_order) => _order.owner.toString() === order.publicKey.toString(), + ); + let _order = null; + if (failAsksFilter.length > 0) { + // eslint-disable-next-line prefer-destructuring + _order = failAsksFilter[0]; + } + if (failBidsFilter.length > 0) { + // eslint-disable-next-line prefer-destructuring + _order = failBidsFilter[0]; + } + if (passAsksFilter.length > 0) { + // eslint-disable-next-line prefer-destructuring + _order = passAsksFilter[0]; + } + if (passBidsFilter.length > 0) { + // eslint-disable-next-line prefer-destructuring + _order = passBidsFilter[0]; + } + if (_order !== null) { + return true; + } + return false; + } + return false; +}; + +export const isCompletedOrder = (order: OpenOrdersAccountWithKey, markets: Markets): boolean => { + const isOpen = isOpenOrder(order, markets); + const isEmpty = + isEmptyOrder(order) && + (order.account.position.asksBaseLots.gt(BN_0) || order.account.position.bidsBaseLots.gt(BN_0)); + return isEmpty && !isOpen; +}; + +export const isBidOrAsk = (order: OpenOrdersAccountWithKey) => { + const isBidSide = order.account.position.bidsBaseLots.gt(order.account.position.asksBaseLots); + if (isBidSide) { + return true; + } + return false; +}; + +export const totalInOrder = (orders: OpenOrdersAccountWithKey[]) => { + let sumOrders = []; + sumOrders = orders?.map( + (order) => + (order.account.position.bidsBaseLots.toNumber() / 10_000 + + order.account.position.asksBaseLots.toNumber() / 10_000) * + order.account.openOrders[0].lockedPrice.toNumber(), + ); + const totalValueLocked = sumOrders.reduce((partialSum, amount) => partialSum + amount, 0); + return numeral(totalValueLocked).format(NUMERAL_FORMAT); +}; + +export const totalUsdcInOrder = (orders: OpenOrdersAccountWithKey[]) => { + let sumOrders = []; + sumOrders = orders.map((order) => { + if (isBidOrAsk(order)) { + return ( + (( + order.account.position.bidsBaseLots.toNumber() + * order.account.openOrders[0].lockedPrice + ) / 10_000) + + (( + order.account.position.asksBaseLots.toNumber() + * order.account.openOrders[0].lockedPrice + ) / 10_000) + ); + } + return 0; + }); + + const totalValueLocked = sumOrders.reduce((partialSum, amount) => partialSum + amount, 0); + return numeral(totalValueLocked).format(NUMERAL_FORMAT); +}; + +export const totalMetaInOrder = (orders: OpenOrdersAccountWithKey[]) => { + let sumOrders = []; + sumOrders = orders.map((order) => { + if (isBidOrAsk(order)) { + return ( + order.account.position.bidsBaseLots.toNumber() + + order.account.position.asksBaseLots.toNumber() + ); + } + return 0; + }); + + const totalValueLocked = sumOrders.reduce((partialSum, amount) => partialSum + amount, 0); + return numeral(totalValueLocked).format(BASE_FORMAT); +}; diff --git a/packages/futarchy-ts/lib/openbookTwap.ts b/packages/futarchy-ts/lib/openbookTwap.ts new file mode 100644 index 00000000..fa1caf6c --- /dev/null +++ b/packages/futarchy-ts/lib/openbookTwap.ts @@ -0,0 +1,22 @@ +import { PublicKey } from '@solana/web3.js'; +import { OPENBOOK_TWAP_PROGRAM_ID, QUOTE_LOTS } from './constants'; +import { TWAPOracle } from './types'; + +export const calculateTWAP = (twapOracle?: TWAPOracle) => { + if (!twapOracle) return undefined; + + // only the initial twap record is recorded, use initial value + if (twapOracle.lastUpdatedSlot.eq(twapOracle.initialSlot)) { + return twapOracle.observationAggregator.toNumber() * QUOTE_LOTS; + } + + const slotsPassed = twapOracle.lastUpdatedSlot.sub(twapOracle.initialSlot); + const twapValue = twapOracle.observationAggregator.div(slotsPassed); + return twapValue.toNumber() * QUOTE_LOTS; +}; + +export const getTwapMarketKey = (market: PublicKey) => + PublicKey.findProgramAddressSync( + [Buffer.from('twap_market'), market.toBuffer()], + OPENBOOK_TWAP_PROGRAM_ID, + )[0]; \ No newline at end of file diff --git a/packages/futarchy-ts/lib/types.ts b/packages/futarchy-ts/lib/types.ts new file mode 100644 index 00000000..0de9b603 --- /dev/null +++ b/packages/futarchy-ts/lib/types.ts @@ -0,0 +1,135 @@ +import { Idl, IdlAccounts, IdlTypes } from '@coral-xyz/anchor'; +import { Connection, PublicKey, Signer, Transaction } from '@solana/web3.js'; +import { AutocratV0 } from './idl/autocrat_v0'; +import { AutocratV0 as AutocratV0_1 } from './idl/autocrat_v0.1'; +import { OpenbookTwap } from './idl/openbook_twap'; +import { OpenbookV2 } from './idl/openbook_v2'; +import { ConditionalVault } from './idl/conditional_vault'; + +type MergeWithOptionalFields = { + [K in keyof (T | U)]: U[K]; +} & { + [K in keyof Omit]?: NonNullable; +} & { + [K in keyof Omit]?: NonNullable; +}; +export type AccountWithKey = { publicKey: PublicKey; account: T }; +export type ProgramVersion = { label: string; programId: PublicKey; idl: Idl }; +export type AutocratProgram = AutocratV0 | AutocratV0_1; +export type DaoState = MergeWithOptionalFields< + IdlAccounts['dao'], + IdlAccounts['dao'] +>; +export type ProposalAccount = MergeWithOptionalFields< + IdlAccounts['proposal'], + IdlAccounts['proposal'] +>; +export type ProposalInstruction = MergeWithOptionalFields< + IdlTypes['ProposalInstruction'], + IdlTypes['ProposalInstruction'] +>; +export type ProposalAccountWithKey = AccountWithKey; +export type VaultAccount = IdlAccounts['conditionalVault']; +export type VaultAccountWithKey = AccountWithKey; +export type TwapMarketAccount = IdlAccounts['twapMarket']; +export type TWAPOracle = IdlTypes['TWAPOracle']; +export type OrderBookSide = { + parsed: { + price: any; + size: any; + }[]; + total: { + price: any; + size: any; + }; + deduped: Map; +}; +export type OrderBook = + | { + passBidsProcessed: OrderBookSide | null; + passAsksProcessed: OrderBookSide | null; + failBidsProcessed: OrderBookSide | null; + failAsksProcessed: OrderBookSide | null; + passBidsArray: any[][]; + passAsksArray: any[][]; + failBidsArray: any[][]; + failAsksArray: any[][]; + passToB: { + topAsk: number; + topBid: number; + }; + failToB: { + topAsk: number; + topBid: number; + }; + passSpreadString: string; + failSpreadString: string; + } + | undefined; +export type Markets = { + pass: MarketAccount; + passAsks: LeafNode[]; + passBids: LeafNode[]; + fail: MarketAccount; + failAsks: LeafNode[]; + failBids: LeafNode[]; + passTwap: TwapMarketAccount; + failTwap: TwapMarketAccount; + baseVault: VaultAccount; + quoteVault: VaultAccount; +}; +export type AllMarketsInfo = { [proposalKey: string]: Markets | undefined }; +export interface InitializedVault { + tx?: Transaction; + signers: Signer[]; + vault: PublicKey; + finalizeMint: PublicKey; + revertMint: PublicKey; +} +export type Proposal = ProposalAccountWithKey & { + title: string; + description: string; +}; + +/// Avoid importing Openbook because it uses a NodeWallet +export type PlaceOrderArgs = IdlTypes['PlaceOrderArgs']; +export type PlaceOrderPeggedArgs = IdlTypes['PlaceOrderPeggedArgs']; +export type OracleConfigParams = IdlTypes['OracleConfigParams']; +export type OracleConfig = IdlTypes['OracleConfig']; +export type MarketAccount = IdlAccounts['market']; +export type MarketAccountWithKey = AccountWithKey; +export type OpenOrdersAccount = IdlAccounts['openOrdersAccount']; +export type OpenOrdersAccountWithKey = AccountWithKey; +export type AllOrders = { [proposalKey: string]: OpenOrdersAccountWithKey[] }; +export type OpenOrdersIndexerAccount = IdlAccounts['openOrdersIndexer']; +export type EventHeapAccount = IdlAccounts['eventHeap']; +export type BookSideAccount = IdlAccounts['bookSide']; +export type LeafNode = IdlTypes['LeafNode']; +export type AnyNode = IdlTypes['AnyNode']; +export type FillEvent = IdlTypes['FillEvent']; +export type OutEvent = IdlTypes['OutEvent']; + +export enum InstructionFieldTypes { + Text, + Number, + BigNumber, + Key, +} +export type InstructionFieldType = { + type: InstructionFieldTypes; + required: boolean; + label: string; + description: string; +}; +export type InstructionAction = { + label: string; + fields: InstructionFieldType[]; + instruction: ( + params: any[], + options?: { connection?: Connection }, + ) => Promise; +}; +export type InstructionSet = { + name: string; + actions: InstructionAction[]; +}; diff --git a/packages/futarchy-ts/lib/utils.ts b/packages/futarchy-ts/lib/utils.ts new file mode 100644 index 00000000..c679b1db --- /dev/null +++ b/packages/futarchy-ts/lib/utils.ts @@ -0,0 +1,36 @@ +import { PublicKey } from '@solana/web3.js'; +import { InstructionFieldTypes } from './types'; + +export const shortKey = (key?: PublicKey | string) => { + if (!key) return '???'; + const str = key?.toString(); + return `${str.substring(0, 4)}...${str.substring(str.length - 5, str.length)}`; +}; + +// Define the debounce function +export function debounce( + callback: (...args: T) => Promise, + delay: number, +): (...args: T) => Promise { + let timerId: NodeJS.Timeout; + return async (...args: T) => { + if (timerId) { + clearTimeout(timerId); + } + timerId = setTimeout(() => { + callback(...args); + }, delay); + }; +} + +export const validateType = async (type: InstructionFieldTypes, value?: string) => { + switch (type) { + case InstructionFieldTypes.Key: + if (!value) { + return false; + } + return /^[1-9A-HJ-NP-Za-km-z]{40,44}$/.test(value); + default: + return true; + } +}; diff --git a/packages/futarchy-ts/package.json b/packages/futarchy-ts/package.json new file mode 100644 index 00000000..ac8253a6 --- /dev/null +++ b/packages/futarchy-ts/package.json @@ -0,0 +1,13 @@ +{ + "name": "@themetadao/futarchy-ts", + "private": "false", + "main": "lib", + "dependencies": { + "@coral-xyz/anchor": "^0.28.1-beta.2", + "@openbook-dex/openbook-v2": "^0.1.9", + "@solana/spl-token": "^0.3.8", + "@solana/web3.js": "^1.90.0", + "@types/numeral": "^2.0.4", + "numeral": "^2.0.6" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 44b44800..820bc4dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,27 +12,6 @@ importers: specifier: 1.0.26 version: 1.0.26 - futarchy-ts: - dependencies: - '@coral-xyz/anchor': - specifier: ^0.28.1-beta.2 - version: 0.28.1-beta.2 - '@openbook-dex/openbook-v2': - specifier: ^0.1.9 - version: 0.1.10 - '@solana/spl-token': - specifier: ^0.3.8 - version: 0.3.8(@solana/web3.js@1.90.0) - '@solana/web3.js': - specifier: ^1.90.0 - version: 1.90.0 - '@types/numeral': - specifier: ^2.0.4 - version: 2.0.5 - numeral: - specifier: ^2.0.6 - version: 2.0.6 - packages/database: dependencies: drizzle-orm: @@ -64,6 +43,27 @@ importers: specifier: ^9.2.14 version: 9.2.14 + packages/futarchy-ts: + dependencies: + '@coral-xyz/anchor': + specifier: ^0.28.1-beta.2 + version: 0.28.1-beta.2 + '@openbook-dex/openbook-v2': + specifier: ^0.1.9 + version: 0.1.10 + '@solana/spl-token': + specifier: ^0.3.8 + version: 0.3.8(@solana/web3.js@1.90.0) + '@solana/web3.js': + specifier: ^1.90.0 + version: 1.90.0 + '@types/numeral': + specifier: ^2.0.4 + version: 2.0.5 + numeral: + specifier: ^2.0.6 + version: 2.0.6 + packages/hasura: dependencies: '@hasura/metadata': @@ -99,7 +99,7 @@ importers: version: 1.90.0 '@themetadao/futarchy-ts': specifier: workspace:* - version: link:../../futarchy-ts + version: link:../futarchy-ts '@themetadao/indexer-db': specifier: workspace:* version: link:../database diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c8b4727c..18ec407e 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,2 @@ packages: - 'packages/*' - - 'futarchy-ts/' \ No newline at end of file