UNPKG

@tribecahq/tribeca-sdk

Version:

The TypeScript SDK for Tribeca, an open standard and toolkit for launching DAOs on Solana.

257 lines 10.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SimpleVoterWrapper = void 0; const tslib_1 = require("tslib"); const solana_contrib_1 = require("@saberhq/solana-contrib"); const token_utils_1 = require("@saberhq/token-utils"); const web3_js_1 = require("@solana/web3.js"); const tiny_invariant_1 = tslib_1.__importDefault(require("tiny-invariant")); const constants_1 = require("../../constants"); const governor_1 = require("../govern/governor"); const pda_1 = require("./pda"); /** * Helper methods around a Simple Voter electorate. */ class SimpleVoterWrapper { constructor(sdk, electorate, governorKey) { this.sdk = sdk; this.electorate = electorate; this.governorKey = governorKey; this.program = sdk.programs.SimpleVoter; this.governor = new governor_1.GovernorWrapper(sdk, governorKey); } get provider() { return this.sdk.provider; } static async load(sdk, electorateKey) { const electorateData = await sdk.programs.SimpleVoter.account.electorate.fetch(electorateKey); const wrapper = new SimpleVoterWrapper(sdk, electorateKey, electorateData.governor); wrapper.electorateData = electorateData; return wrapper; } async fetchProposalData(proposalKey) { return await this.sdk.programs.Govern.account.proposal.fetch(proposalKey); } async fetchTokenRecord(tokenRecordKey) { return await this.program.account.tokenRecord.fetch(tokenRecordKey); } async fetchVoterMetadata() { (0, tiny_invariant_1.default)(this.electorate, "electorate not set"); this.electorateData = await this.program.account.electorate.fetch(this.electorate); return this.electorateData; } async getOrCreateTokenRecord(authority = this.sdk.provider.wallet.publicKey) { (0, tiny_invariant_1.default)(this.electorate, "electorate not set"); const [tokenRecord] = await (0, pda_1.findTokenRecordAddress)(authority, this.electorate); try { await this.program.account.tokenRecord.fetch(tokenRecord); return { tokenRecord, instruction: null }; } catch { return { tokenRecord, instruction: await this.initializeTokenRecordIx(authority), }; } } async depositTokens(amount, authority = this.sdk.provider.wallet.publicKey) { (0, tiny_invariant_1.default)(this.electorate, "electorate not set"); const { tokenRecord, instruction: initTokenRecordIx } = await this.getOrCreateTokenRecord(authority); const { govTokenAccount, govTokenVault, instructions } = await this._getOrCreateGovTokenATAsInternal(authority, tokenRecord); if (initTokenRecordIx) { instructions.push(initTokenRecordIx); } instructions.push(this.program.instruction.depositTokens(amount, { accounts: { authority, govTokenAccount, govTokenVault, tokenRecord, tokenProgram: token_utils_1.TOKEN_PROGRAM_ID, }, })); return new solana_contrib_1.TransactionEnvelope(this.sdk.provider, instructions); } async withdrawTokens(amount, authority) { (0, tiny_invariant_1.default)(this.electorate, "electorate not set"); (0, tiny_invariant_1.default)(this.electorateData, "electorate data not loaded"); const [tokenRecord] = await (0, pda_1.findTokenRecordAddress)(authority, this.electorate); const { govTokenAccount, govTokenVault, instructions } = await this._getOrCreateGovTokenATAsInternal(authority, tokenRecord); instructions.push(this.program.instruction.withdrawTokens(amount, { accounts: { authority, govTokenAccount, govTokenVault, tokenRecord, tokenProgram: token_utils_1.TOKEN_PROGRAM_ID, }, })); return new solana_contrib_1.TransactionEnvelope(this.sdk.provider, instructions); } activateProposal(proposal) { const ix = this.program.instruction.activateProposal({ accounts: { electorate: this.electorate, governor: this.governorKey, proposal, governProgram: constants_1.TRIBECA_ADDRESSES.Govern, }, }); return new solana_contrib_1.TransactionEnvelope(this.sdk.provider, [ix]); } async castVotes(args) { (0, tiny_invariant_1.default)(this.electorateData, "electorate data not loaded"); const { authority = this.provider.wallet.publicKey, proposal, voteSide, reason, } = args; const ixs = []; const { tokenRecord, instruction: tokenRecordIx } = await this.getOrCreateTokenRecord(authority); if (tokenRecordIx) { ixs.push(tokenRecordIx); } const { voteKey, instruction: createVoteIX } = await this.governor.getOrCreateVote({ proposal, voter: authority, }); if (createVoteIX) { ixs.push(createVoteIX); } ixs.push(this.program.instruction.castVotes(voteSide, { accounts: { electorate: this.electorate, authority: authority !== null && authority !== void 0 ? authority : this.sdk.provider.wallet.publicKey, proposal, tokenRecord, vote: voteKey, tribeca: this._genTribecaContext(), }, })); if (reason) { ixs.push((0, solana_contrib_1.createMemoInstruction)(reason, [authority])); } return new solana_contrib_1.TransactionEnvelope(this.sdk.provider, ixs); } async withdrawVotes(proposal, authority = this.sdk.provider.wallet.publicKey) { (0, tiny_invariant_1.default)(this.electorateData, "electorate data not loaded"); const ixs = []; const { tokenRecord, instruction: tokenRecordIx } = await this.getOrCreateTokenRecord(authority); if (tokenRecordIx) { ixs.push(tokenRecordIx); } const { voteKey, instruction: voteRecieptIx } = await this.governor.getOrCreateVote({ proposal, }); if (voteRecieptIx) { ixs.push(voteRecieptIx); } ixs.push(this.program.instruction.withdrawVotes({ accounts: { electorate: this.electorate, authority, proposal, tokenRecord, vote: voteKey, tribeca: this._genTribecaContext(), }, })); return new solana_contrib_1.TransactionEnvelope(this.sdk.provider, ixs); } async depositTokenAndCastVote(args) { const { amount, proposal, voteSide, reason, authority = this.provider.wallet.publicKey, } = args; const { tokenRecord, instruction: tokenRecordIx } = await this.getOrCreateTokenRecord(authority); const { govTokenAccount, govTokenVault, instructions } = await this._getOrCreateGovTokenATAsInternal(authority, tokenRecord); if (tokenRecordIx) { instructions.push(tokenRecordIx); } const { voteKey, instruction: createVoteIX } = await this.governor.getOrCreateVote({ proposal, voter: authority, }); if (createVoteIX) { instructions.push(createVoteIX); } instructions.push(this.program.instruction.depositTokens(amount, { accounts: { authority, govTokenAccount, govTokenVault, tokenRecord, tokenProgram: token_utils_1.TOKEN_PROGRAM_ID, }, })); return new solana_contrib_1.TransactionEnvelope(this.sdk.provider, instructions.concat(this._genCastVotesInstructions({ proposal, authority, voteSide, reason, vote: voteKey, tokenRecord, }))); } async initializeTokenRecordIx(authority = this.sdk.provider.wallet.publicKey) { (0, tiny_invariant_1.default)(this.electorate, "electorate not set"); (0, tiny_invariant_1.default)(this.electorateData, "electorate data not loaded"); const [tokenRecord, bump] = await (0, pda_1.findTokenRecordAddress)(authority, this.electorate); return this.program.instruction.initializeTokenRecord(bump, { accounts: { authority, tokenRecord, electorate: this.electorate, govTokenVault: await (0, token_utils_1.getATAAddress)({ mint: this.electorateData.govTokenMint, owner: tokenRecord, }), payer: this.sdk.provider.wallet.publicKey, systemProgram: web3_js_1.SystemProgram.programId, }, }); } _genCastVotesInstructions(args) { var _a; const { proposal, voteSide, reason, tokenRecord, vote } = args; const authority = (_a = args.authority) !== null && _a !== void 0 ? _a : this.provider.wallet.publicKey; const ixs = []; ixs.push(this.program.instruction.castVotes(voteSide, { accounts: { electorate: this.electorate, authority, proposal, tokenRecord, vote, tribeca: this._genTribecaContext(), }, })); if (reason) { ixs.push((0, solana_contrib_1.createMemoInstruction)(reason, [authority])); } return ixs; } _genTribecaContext() { (0, tiny_invariant_1.default)(this.electorateData, "electrate data not loaded"); return { governor: this.electorateData.governor, program: constants_1.TRIBECA_ADDRESSES.Govern, }; } async _getOrCreateGovTokenATAsInternal(authority, tokenRecord) { (0, tiny_invariant_1.default)(this.electorateData, "electorate data not loaded"); const { provider } = this.sdk; const { address: govTokenAccount, instruction: ix1 } = await (0, token_utils_1.getOrCreateATA)({ provider, mint: this.electorateData.govTokenMint, owner: authority, payer: authority, }); const { address: govTokenVault, instruction: ix2 } = await (0, token_utils_1.getOrCreateATA)({ provider, mint: this.electorateData.govTokenMint, owner: tokenRecord, payer: authority, }); return { govTokenAccount, govTokenVault, instructions: [ix1, ix2].filter((ix) => !!ix), }; } } exports.SimpleVoterWrapper = SimpleVoterWrapper; //# sourceMappingURL=electorate.js.map