Skip to content

Commit

Permalink
Merge branch 'tupui:main' into vote-execute
Browse files Browse the repository at this point in the history
  • Loading branch information
0xExp-po authored Dec 17, 2024
2 parents dfb9e94 + 2a0f72f commit e4ce5c3
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 12 deletions.
49 changes: 49 additions & 0 deletions contracts/versioning/src/contract_dao.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,55 @@ impl DaoTrait for Tansu {
}
}

fn execute(
env: Env,
maintainer: Address,
project_key: Bytes,
proposal_id: u32,
) -> types::ProposalStatus {
maintainer.require_auth();

let project_key_ = project_key.clone();
let page = proposal_id / MAX_PROPOSALS_PER_PAGE;
let sub_id = proposal_id % MAX_PROPOSALS_PER_PAGE;
let mut dao_page = <Tansu as DaoTrait>::get_dao(env.clone(), project_key_.clone(), page);
let mut proposal = match dao_page.proposals.try_get(sub_id) {
Ok(Some(proposal)) => proposal,
_ => panic_with_error!(&env, &errors::ContractErrors::NoProposalorPageFound),
};

let curr_timestamp = env.ledger().timestamp();

// only allow to execute once
if proposal.status != types::ProposalStatus::Active {
panic_with_error!(&env, &errors::ContractErrors::AlreadyExecuted);
} else if curr_timestamp < proposal.voting_ends_at {
panic_with_error!(&env, &errors::ContractErrors::ProposalVotingTime);
} else {
// count votes
let voted_approve = proposal.voters_approve.len();
let voted_reject = proposal.voters_reject.len();
let voted_abstain = proposal.voters_abstain.len();

// accept or reject if we have a majority
if voted_approve > (voted_abstain + voted_reject) {
proposal.status = types::ProposalStatus::Approved;
} else if voted_reject > (voted_abstain + voted_approve) {
proposal.status = types::ProposalStatus::Rejected;
} else {
proposal.status = types::ProposalStatus::Cancelled
}

dao_page.proposals.set(sub_id, proposal.clone());

env.storage()
.persistent()
.set(&types::ProjectKey::Dao(project_key_, page), &dao_page);

proposal.status
}
}

/// Get one page of proposal of the DAO.
/// A page has 0 to MAX_PROPOSALS_PER_PAGE proposals.
/// # Arguments
Expand Down
1 change: 1 addition & 0 deletions contracts/versioning/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ pub enum ContractErrors {
NoProposalorPageFound = 8,
AlreadyVoted = 9,
ProposalVotingTime = 10,
AlreadyExecuted = 11,
}
7 changes: 7 additions & 0 deletions contracts/versioning/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ pub trait DaoTrait {

fn vote(env: Env, voter: Address, project_key: Bytes, proposal_id: u32, vote: types::Vote);

fn execute(
env: Env,
maintainer: Address,
project_key: Bytes,
proposal_id: u32,
) -> types::ProposalStatus;

fn get_dao(env: Env, project_key: Bytes, page: u32) -> types::Dao;

fn get_proposal(env: Env, project_key: Bytes, proposal_id: u32) -> types::Proposal;
Expand Down
32 changes: 31 additions & 1 deletion contracts/versioning/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
use super::{domain_contract, Tansu, TansuClient};
use crate::contract_versioning::{domain_node, domain_register};
use crate::errors::ContractErrors;
use crate::types::{Dao, Vote};
use crate::types::{Dao, ProposalStatus, Vote};
use soroban_sdk::testutils::Address as _;
use soroban_sdk::testutils::Ledger as _;
use soroban_sdk::{
symbol_short, testutils::Events, token, vec, Address, Bytes, Env, IntoVal, String, Vec,
};
Expand Down Expand Up @@ -228,9 +229,38 @@ fn test() {
assert_eq!(error, ContractErrors::AlreadyVoted.into());

let proposal = contract.get_proposal(&id, &proposal_id);
assert_eq!(proposal.status, ProposalStatus::Active);
assert_eq!(proposal.voters_approve, vec![&env, mando.clone()]);
assert_eq!(proposal.voters_reject, Vec::new(&env));
assert_eq!(proposal.voters_abstain, vec![&env, grogu.clone()]);

// cast another vote and approve
env.ledger().set_timestamp(1234567890);
let kuiil = Address::generate(&env);
let voting_ends_at = 1234567890 + 3600 * 24 * 2;
let proposal_id_2 = contract.create_proposal(&grogu, &id, &title, &ipfs, &voting_ends_at);
contract.vote(&mando, &id, &proposal_id_2, &Vote::Approve);
contract.vote(&kuiil, &id, &proposal_id_2, &Vote::Approve);

// too early to execute
let error = contract
.try_execute(&mando, &id, &proposal_id_2)
.unwrap_err()
.unwrap();
assert_eq!(error, ContractErrors::ProposalVotingTime.into());

env.ledger().set_timestamp(voting_ends_at + 1);

let vote_result = contract.execute(&mando, &id, &proposal_id_2);
assert_eq!(vote_result, ProposalStatus::Approved);
let proposal_2 = contract.get_proposal(&id, &proposal_id_2);
assert_eq!(
proposal_2.voters_approve,
vec![&env, mando.clone(), kuiil.clone()]
);
assert_eq!(proposal_2.voters_reject, Vec::new(&env));
assert_eq!(proposal_2.voters_abstain, vec![&env, grogu.clone()]);
assert_eq!(proposal_2.status, ProposalStatus::Approved);
}

#[test]
Expand Down
1 change: 0 additions & 1 deletion dapp/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ import netlify from "@astrojs/netlify";
// https://astro.build/config
export default defineConfig({
integrations: [react(), tailwind()],
output: "hybrid",
adapter: netlify(),
});
Binary file modified dapp/bun.lockb
Binary file not shown.
6 changes: 3 additions & 3 deletions dapp/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"dependencies": {
"@astrojs/check": "^0.9.4",
"@astrojs/netlify": "^5.5.4",
"@astrojs/react": "^4.0.0",
"@astrojs/netlify": "^6.0.1",
"@astrojs/react": "^4.1.1",
"@astrojs/tailwind": "5.1.3",
"@creit.tech/sorobandomains-sdk": "^0.1.4",
"@creit.tech/stellar-wallets-kit": "^1.3.0",
Expand All @@ -11,7 +11,7 @@
"@stellar/stellar-sdk": "^13.0.0",
"@stellar/stellar-xdr-json": "^22.0.0-rc.1.1",
"@web3-storage/w3up-client": "^16.5.2",
"astro": "4.16.17",
"astro": "5.0.8",
"astro-seo": "^0.8.4",
"crypto-js": "^4.2.0",
"github-markdown-css": "^5.8.1",
Expand Down
4 changes: 2 additions & 2 deletions dapp/packages/soroban_versioning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This library was automatically generated by Soroban CLI using a command similar
soroban contract bindings ts \
--rpc-url https://soroban-testnet.stellar.org \
--network-passphrase "Test SDF Network ; September 2015" \
--contract-id CCHZAAUJJZOCFZVTQWGZU4PXR7SFB5PL3XBSHUBNQPXJ3KWE4VFHOBE5 \
--contract-id CB6EA5V4T5Z5XXOKHRU5MNYTZ2QESR4STUW6EBLA4HXYZ2BPVMCHRHUR \
--output-dir ./path/to/soroban_versioning
```

Expand All @@ -30,7 +30,7 @@ However, we've actually encountered [frustration](https://github.com/stellar/sor

```json
"scripts": {
"postinstall": "soroban contract bindings ts --rpc-url https://soroban-testnet.stellar.org --network-passphrase \"Test SDF Network ; September 2015\" --id CCHZAAUJJZOCFZVTQWGZU4PXR7SFB5PL3XBSHUBNQPXJ3KWE4VFHOBE5 --name soroban_versioning"
"postinstall": "soroban contract bindings ts --rpc-url https://soroban-testnet.stellar.org --network-passphrase \"Test SDF Network ; September 2015\" --id CB6EA5V4T5Z5XXOKHRU5MNYTZ2QESR4STUW6EBLA4HXYZ2BPVMCHRHUR --name soroban_versioning"
}
```

Expand Down
34 changes: 33 additions & 1 deletion dapp/packages/soroban_versioning/dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export * as rpc from "@stellar/stellar-sdk/rpc";
export declare const networks: {
readonly testnet: {
readonly networkPassphrase: "Test SDF Network ; September 2015";
readonly contractId: "CCHZAAUJJZOCFZVTQWGZU4PXR7SFB5PL3XBSHUBNQPXJ3KWE4VFHOBE5";
readonly contractId: "CB6EA5V4T5Z5XXOKHRU5MNYTZ2QESR4STUW6EBLA4HXYZ2BPVMCHRHUR";
};
};
export declare const Errors: {
Expand Down Expand Up @@ -48,6 +48,9 @@ export declare const Errors: {
10: {
message: string;
};
11: {
message: string;
};
};
export type DataKey = {
tag: "Admin";
Expand Down Expand Up @@ -205,6 +208,34 @@ export interface Client {
simulate?: boolean;
},
) => Promise<AssembledTransaction<null>>;
/**
* Construct and simulate a execute transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
*/
execute: (
{
maintainer,
project_key,
proposal_id,
}: {
maintainer: string;
project_key: Buffer;
proposal_id: u32;
},
options?: {
/**
* The fee to pay for the transaction. Default: BASE_FEE
*/
fee?: number;
/**
* The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT
*/
timeoutInSeconds?: number;
/**
* Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true
*/
simulate?: boolean;
},
) => Promise<AssembledTransaction<ProposalStatus>>;
/**
* Construct and simulate a get_dao transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object.
* Get one page of proposal of the DAO.
Expand Down Expand Up @@ -466,6 +497,7 @@ export declare class Client extends ContractClient {
readonly fromJSON: {
create_proposal: (json: string) => AssembledTransaction<number>;
vote: (json: string) => AssembledTransaction<null>;
execute: (json: string) => AssembledTransaction<ProposalStatus>;
get_dao: (json: string) => AssembledTransaction<Dao>;
get_proposal: (json: string) => AssembledTransaction<Proposal>;
upgrade: (json: string) => AssembledTransaction<null>;
Expand Down
7 changes: 5 additions & 2 deletions dapp/packages/soroban_versioning/dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ if (typeof window !== "undefined") {
export const networks = {
testnet: {
networkPassphrase: "Test SDF Network ; September 2015",
contractId: "CCHZAAUJJZOCFZVTQWGZU4PXR7SFB5PL3XBSHUBNQPXJ3KWE4VFHOBE5",
contractId: "CB6EA5V4T5Z5XXOKHRU5MNYTZ2QESR4STUW6EBLA4HXYZ2BPVMCHRHUR",
},
};
export const Errors = {
Expand All @@ -28,6 +28,7 @@ export const Errors = {
8: { message: "NoProposalorPageFound" },
9: { message: "AlreadyVoted" },
10: { message: "ProposalVotingTime" },
11: { message: "AlreadyExecuted" },
};
export class Client extends ContractClient {
options;
Expand All @@ -36,6 +37,7 @@ export class Client extends ContractClient {
new ContractSpec([
"AAAAAAAAAcFDcmVhdGUgYSBwcm9wb3NhbCBvbiB0aGUgREFPIG9mIHRoZSBwcm9qZWN0LgpQcm9wb3NhbCBpbml0aWF0b3JzIGFyZSBhdXRvbWF0aWNhbGx5IHB1dCBpbiB0aGUgYWJzdGFpbiBncm91cC4KIyBBcmd1bWVudHMKKiBgZW52YCAtIFRoZSBlbnZpcm9ubWVudCBvYmplY3QKKiBgcHJvcG9zZXJgIC0gQWRkcmVzcyBvZiB0aGUgcHJvcG9zYWwgY3JlYXRvcgoqIGBwcm9qZWN0X2tleWAgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHByb2plY3QKKiBgdGl0bGVgIC0gVGl0bGUgb2YgdGhlIHByb3Bvc2FsCiogYGlwZnNgIC0gSVBGUyBjb250ZW50IGlkZW50aWZpZXIgZGVzY3JpYmluZyB0aGUgcHJvcG9zYWwKKiBgdm90aW5nX2VuZHNfYXRgIC0gVU5JWCB0aW1lc3RhbXAgd2hlbiB2b3RpbmcgZW5kcwojIFJldHVybnMKKiBgdTMyYCAtIFRoZSBJRCBvZiB0aGUgY3JlYXRlZCBwcm9wb3NhbAAAAAAAAA9jcmVhdGVfcHJvcG9zYWwAAAAABQAAAAAAAAAIcHJvcG9zZXIAAAATAAAAAAAAAAtwcm9qZWN0X2tleQAAAAAOAAAAAAAAAAV0aXRsZQAAAAAAABAAAAAAAAAABGlwZnMAAAAQAAAAAAAAAA52b3RpbmdfZW5kc19hdAAAAAAABgAAAAEAAAAE",
"AAAAAAAAAQ5DYXN0IGEgdm90ZSBvbiBhIHByb3Bvc2FsLgpEb3VibGUgdm90ZXMgYXJlIG5vdCBhbGxvd2VkLgojIEFyZ3VtZW50cwoqIGBlbnZgIC0gVGhlIGVudmlyb25tZW50IG9iamVjdAoqIGB2b3RlcmAgLSBBZGRyZXNzIG9mIHRoZSB2b3RlcgoqIGBwcm9qZWN0X2tleWAgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHByb2plY3QKKiBgcHJvcG9zYWxfaWRgIC0gSUQgb2YgdGhlIHByb3Bvc2FsCiogYHZvdGVgIC0gQXBwcm92ZSwgcmVqZWN0IG9yIGFic3RhaW4gZGVjaXNpb24AAAAAAAR2b3RlAAAABAAAAAAAAAAFdm90ZXIAAAAAAAATAAAAAAAAAAtwcm9qZWN0X2tleQAAAAAOAAAAAAAAAAtwcm9wb3NhbF9pZAAAAAAEAAAAAAAAAAR2b3RlAAAH0AAAAARWb3RlAAAAAA==",
"AAAAAAAAAAAAAAAHZXhlY3V0ZQAAAAADAAAAAAAAAAptYWludGFpbmVyAAAAAAATAAAAAAAAAAtwcm9qZWN0X2tleQAAAAAOAAAAAAAAAAtwcm9wb3NhbF9pZAAAAAAEAAAAAQAAB9AAAAAOUHJvcG9zYWxTdGF0dXMAAA==",
"AAAAAAAAARRHZXQgb25lIHBhZ2Ugb2YgcHJvcG9zYWwgb2YgdGhlIERBTy4KQSBwYWdlIGhhcyAwIHRvIE1BWF9QUk9QT1NBTFNfUEVSX1BBR0UgcHJvcG9zYWxzLgojIEFyZ3VtZW50cwoqIGBlbnZgIC0gVGhlIGVudmlyb25tZW50IG9iamVjdAoqIGBwcm9qZWN0X2tleWAgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHByb2plY3QKKiBgcGFnZWAgLSBQYWdlIG9mIHByb3Bvc2FscwojIFJldHVybnMKKiBgdHlwZXM6OkRhb2AgLSBUaGUgRGFvIG9iamVjdCAodmVjdG9yIG9mIHByb3Bvc2FscykAAAAHZ2V0X2RhbwAAAAACAAAAAAAAAAtwcm9qZWN0X2tleQAAAAAOAAAAAAAAAARwYWdlAAAABAAAAAEAAAfQAAAAA0RhbwA=",
"AAAAAAAAANdPbmx5IHJldHVybiBhIHNpbmdsZSBwcm9wb3NhbAojIEFyZ3VtZW50cwoqIGBlbnZgIC0gVGhlIGVudmlyb25tZW50IG9iamVjdAoqIGBwcm9qZWN0X2tleWAgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHByb2plY3QKKiBgcHJvcG9zYWxfaWRgIC0gSUQgb2YgdGhlIHByb3Bvc2FsCiMgUmV0dXJucwoqIGB0eXBlczo6UHJvcG9zYWxgIC0gVGhlIHByb3Bvc2FsIG9iamVjdAAAAAAMZ2V0X3Byb3Bvc2FsAAAAAgAAAAAAAAALcHJvamVjdF9rZXkAAAAADgAAAAAAAAALcHJvcG9zYWxfaWQAAAAABAAAAAEAAAfQAAAACFByb3Bvc2Fs",
"AAAAAAAAAAAAAAANX19jb25zdHJ1Y3RvcgAAAAAAAAEAAAAAAAAABWFkbWluAAAAAAAAEwAAAAA=",
Expand All @@ -46,7 +48,7 @@ export class Client extends ContractClient {
"AAAAAAAAABhTZXQgdGhlIGxhc3QgY29tbWl0IGhhc2gAAAAGY29tbWl0AAAAAAADAAAAAAAAAAptYWludGFpbmVyAAAAAAATAAAAAAAAAAtwcm9qZWN0X2tleQAAAAAOAAAAAAAAAARoYXNoAAAAEAAAAAA=",
"AAAAAAAAABhHZXQgdGhlIGxhc3QgY29tbWl0IGhhc2gAAAAKZ2V0X2NvbW1pdAAAAAAAAQAAAAAAAAALcHJvamVjdF9rZXkAAAAADgAAAAEAAAAQ",
"AAAAAAAAAAAAAAALZ2V0X3Byb2plY3QAAAAAAQAAAAAAAAALcHJvamVjdF9rZXkAAAAADgAAAAEAAAfQAAAAB1Byb2plY3QA",
"AAAABAAAAAAAAAAAAAAADkNvbnRyYWN0RXJyb3JzAAAAAAALAAAAAAAAAA9VbmV4cGVjdGVkRXJyb3IAAAAAAAAAAAAAAAAKSW52YWxpZEtleQAAAAAAAQAAAAAAAAATUHJvamVjdEFscmVhZHlFeGlzdAAAAAACAAAAAAAAABZVbnJlZ2lzdGVyZWRNYWludGFpbmVyAAAAAAADAAAAAAAAAAtOb0hhc2hGb3VuZAAAAAAEAAAAAAAAABJJbnZhbGlkRG9tYWluRXJyb3IAAAAAAAUAAAAAAAAAGE1haW50YWluZXJOb3REb21haW5Pd25lcgAAAAYAAAAAAAAAF1Byb3Bvc2FsSW5wdXRWYWxpZGF0aW9uAAAAAAcAAAAAAAAAFU5vUHJvcG9zYWxvclBhZ2VGb3VuZAAAAAAAAAgAAAAAAAAADEFscmVhZHlWb3RlZAAAAAkAAAAAAAAAElByb3Bvc2FsVm90aW5nVGltZQAAAAAACg==",
"AAAABAAAAAAAAAAAAAAADkNvbnRyYWN0RXJyb3JzAAAAAAAMAAAAAAAAAA9VbmV4cGVjdGVkRXJyb3IAAAAAAAAAAAAAAAAKSW52YWxpZEtleQAAAAAAAQAAAAAAAAATUHJvamVjdEFscmVhZHlFeGlzdAAAAAACAAAAAAAAABZVbnJlZ2lzdGVyZWRNYWludGFpbmVyAAAAAAADAAAAAAAAAAtOb0hhc2hGb3VuZAAAAAAEAAAAAAAAABJJbnZhbGlkRG9tYWluRXJyb3IAAAAAAAUAAAAAAAAAGE1haW50YWluZXJOb3REb21haW5Pd25lcgAAAAYAAAAAAAAAF1Byb3Bvc2FsSW5wdXRWYWxpZGF0aW9uAAAAAAcAAAAAAAAAFU5vUHJvcG9zYWxvclBhZ2VGb3VuZAAAAAAAAAgAAAAAAAAADEFscmVhZHlWb3RlZAAAAAkAAAAAAAAAElByb3Bvc2FsVm90aW5nVGltZQAAAAAACgAAAAAAAAAPQWxyZWFkeUV4ZWN1dGVkAAAAAAs=",
"AAAAAgAAAAAAAAAAAAAAB0RhdGFLZXkAAAAAAQAAAAAAAAAAAAAABUFkbWluAAAA",
"AAAAAgAAAAAAAAAAAAAADlByb3Bvc2FsU3RhdHVzAAAAAAAEAAAAAAAAAAAAAAAGQWN0aXZlAAAAAAAAAAAAAAAAAAhBcHByb3ZlZAAAAAAAAAAAAAAACFJlamVjdGVkAAAAAAAAAAAAAAAJQ2FuY2VsbGVkAAAA",
"AAAAAgAAAAAAAAAAAAAABFZvdGUAAAADAAAAAAAAAAAAAAAHQXBwcm92ZQAAAAAAAAAAAAAAAAZSZWplY3QAAAAAAAAAAAAAAAAAB0Fic3RhaW4A",
Expand All @@ -63,6 +65,7 @@ export class Client extends ContractClient {
fromJSON = {
create_proposal: this.txFromJSON,
vote: this.txFromJSON,
execute: this.txFromJSON,
get_dao: this.txFromJSON,
get_proposal: this.txFromJSON,
upgrade: this.txFromJSON,
Expand Down
Loading

0 comments on commit e4ce5c3

Please sign in to comment.