@leofcoin/contracts 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +5 -2
- package/README.md +27 -1
- package/exports/chat.d.ts +12 -0
- package/exports/factory.d.ts +3 -3
- package/exports/factory.js +1 -1
- package/exports/name-service.d.ts +1 -1
- package/exports/name-service.js +1 -1
- package/exports/native-token.d.ts +2 -1
- package/exports/native-token.js +1 -1
- package/exports/power-token.d.ts +2 -1
- package/exports/power-token.js +1 -1
- package/exports/src/factory.d.ts +4 -3
- package/exports/src/name-service.d.ts +2 -1
- package/exports/src/validators.d.ts +19 -4
- package/exports/validators.d.ts +22 -7
- package/exports/validators.js +1 -1
- package/package.json +13 -11
- package/src/factory.ts +4 -4
- package/src/name-service.ts +1 -1
- package/src/native-token.ts +4 -3
- package/src/power-token.ts +4 -3
- package/src/validators.ts +36 -18
- package/test/factory.js +66 -0
- package/test/native-token.js +96 -0
- package/test/validators.js +120 -0
- package/tsconfig.json +2 -1
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/src/types.ts +0 -2
package/.prettierrc
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
"tabWidth": 2,
|
|
3
3
|
"semi": false,
|
|
4
4
|
"singleQuote": true,
|
|
5
|
-
"printWidth":
|
|
5
|
+
"printWidth": 100,
|
|
6
|
+
"bracketSpacing": true,
|
|
6
7
|
"trailingComma": "none",
|
|
7
|
-
"bracketSameLine": true
|
|
8
|
+
"bracketSameLine": true,
|
|
9
|
+
"arrowParens": "always",
|
|
10
|
+
"singleAttributePerLine": true
|
|
8
11
|
}
|
package/README.md
CHANGED
|
@@ -1,2 +1,28 @@
|
|
|
1
1
|
# contracts
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
## Leofcoin Class
|
|
4
|
+
|
|
5
|
+
The `Leofcoin` class extends the `Token` class from the `@leofcoin/standards/token.js` module. It represents a specific type of token with predefined properties.
|
|
6
|
+
|
|
7
|
+
### Constructor
|
|
8
|
+
|
|
9
|
+
#### `constructor(state: TokenState)`
|
|
10
|
+
|
|
11
|
+
Creates an instance of the `Leofcoin` class.
|
|
12
|
+
|
|
13
|
+
##### Parameters
|
|
14
|
+
|
|
15
|
+
- `state` (TokenState): The initial state of the token.
|
|
16
|
+
|
|
17
|
+
##### Example
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import Leofcoin from './native-token'
|
|
21
|
+
import { TokenState } from '@leofcoin/standards/token.js'
|
|
22
|
+
|
|
23
|
+
const initialState: TokenState = {
|
|
24
|
+
// Define the initial state properties here
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const leofcoin = new Leofcoin(initialState)
|
|
28
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TokenReceiver } from '@leofcoin/standards';
|
|
2
|
+
import { TokenReceiverState } from '@leofcoin/standards/token-receiver';
|
|
3
|
+
export interface chatState extends TokenReceiverState {
|
|
4
|
+
nicknames: {
|
|
5
|
+
[address: string]: string;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export default class Chat extends TokenReceiver {
|
|
9
|
+
#private;
|
|
10
|
+
constructor(tokenToReceive: any, tokenAmountToReceive: any, state: any);
|
|
11
|
+
changeNickName(newName: string): Promise<void>;
|
|
12
|
+
}
|
package/exports/factory.d.ts
CHANGED
|
@@ -3,15 +3,15 @@ import type { PublicVotingState } from '@leofcoin/standards/public-voting';
|
|
|
3
3
|
import { TokenReceiverState } from '@leofcoin/standards/token-receiver';
|
|
4
4
|
export interface FactoryState extends TokenReceiverState {
|
|
5
5
|
contracts: any[];
|
|
6
|
-
totalContracts:
|
|
6
|
+
totalContracts: bigint;
|
|
7
7
|
}
|
|
8
8
|
export default class Factory extends TokenReceiver {
|
|
9
9
|
#private;
|
|
10
|
-
constructor(tokenToReceive: address, tokenAmountToReceive:
|
|
10
|
+
constructor(tokenToReceive: address, tokenAmountToReceive: bigint, state: FactoryState);
|
|
11
11
|
get state(): PublicVotingState;
|
|
12
12
|
get name(): string;
|
|
13
13
|
get contracts(): string[];
|
|
14
|
-
get totalContracts():
|
|
14
|
+
get totalContracts(): bigint;
|
|
15
15
|
isRegistered(address: any): boolean;
|
|
16
16
|
/**
|
|
17
17
|
*
|
package/exports/factory.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Voting extends ContractCreator{#votes={};#votingDisabled=!1;#votingDuration=1728e5;constructor(state){super(state),state&&(this.#votes=state.votes,this.#votingDisabled=state.votingDisabled,this.#votingDuration=state.votingDuration)}get votes(){return{...this.#votes}}get votingDuration(){return this.#votingDuration}get votingDisabled(){return this.#votingDisabled}get state(){return{...super.state,votes:this.#votes,votingDisabled:this.#votingDisabled,votingDuration:this.#votingDuration}}#canVote(){return this._canVote?.()}#beforeVote(){return this._beforeVote?.()}#afterVote(){return this._afterVote?.()}createVote(title,description,endTime,method,args=[]){if(!this.#canVote())throw new Error("Not allowed to create a vote");const id=crypto.randomUUID();this.#votes[id]={title:title,description:description,method:method,endTime:endTime,args:args}}#endVoting(voteId){let agree=Object.values(this.#votes[voteId].results).filter((result=>1===result)),disagree=Object.values(this.#votes[voteId].results).filter((result=>0===result));agree.length>disagree.length&&this[this.#votes[voteId].method](...this.#votes[voteId].args),this.#votes[voteId].finished=!0}async vote(voteId,vote){if(0!==(vote=Number(vote))&&.5!==vote&&1!==vote)throw new Error(`invalid vote value ${vote}`);if(!this.#votes[voteId])throw new Error(`Nothing found for ${voteId}`);const ended=(new Date).getTime()>this.#votes[voteId].endTime;if(ended&&!this.#votes[voteId].finished&&this.#endVoting(voteId),ended)throw new Error("voting already ended");if(!this.#canVote())throw new Error("Not allowed to vote");await this.#beforeVote(),this.#votes[voteId][msg.sender]=vote,await this.#afterVote()}get votesInProgress(){return Object.entries(this.#votes).filter((([id,vote])=>!vote.finished)).map((([id,vote])=>({...vote,id:id})))}#disableVoting(){this.#votingDisabled=!0}disableVoting(){if(!this.#canVote())throw new Error("not a allowed");this.createVote("disable voting","Warning this disables all voting features forever",(new Date).getTime()+this.#votingDuration,"#disableVoting",[])}sync(){for(const vote of this.votesInProgress)vote.endTime<(new Date).getTime()&&this.#endVoting(vote.id)}}class PublicVoting extends Voting{constructor(state){super(state)}}class TokenReceiver extends PublicVoting{#tokenToReceive;#tokenAmountToReceive;#tokenReceiver;#voteType="transfer";constructor(tokenToReceive,tokenAmountToReceive,burns,state){super(state),state?(this.#tokenReceiver=state.tokenReceiver,this.#tokenToReceive=state.tokenToReceive,this.#tokenAmountToReceive=
|
|
1
|
+
class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Voting extends ContractCreator{#votes={};#votingDisabled=!1;#votingDuration=1728e5;constructor(state){super(state),state&&(this.#votes=state.votes,this.#votingDisabled=state.votingDisabled,this.#votingDuration=state.votingDuration)}get votes(){return{...this.#votes}}get votingDuration(){return this.#votingDuration}get votingDisabled(){return this.#votingDisabled}get state(){return{...super.state,votes:this.#votes,votingDisabled:this.#votingDisabled,votingDuration:this.#votingDuration}}#canVote(){return this._canVote?.()}#beforeVote(){return this._beforeVote?.()}#afterVote(){return this._afterVote?.()}createVote(title,description,endTime,method,args=[]){if(!this.#canVote())throw new Error("Not allowed to create a vote");const id=crypto.randomUUID();this.#votes[id]={title:title,description:description,method:method,endTime:endTime,args:args}}#endVoting(voteId){let agree=Object.values(this.#votes[voteId].results).filter((result=>1===result)),disagree=Object.values(this.#votes[voteId].results).filter((result=>0===result));agree.length>disagree.length&&this[this.#votes[voteId].method](...this.#votes[voteId].args),this.#votes[voteId].finished=!0}async vote(voteId,vote){if(0!==(vote=Number(vote))&&.5!==vote&&1!==vote)throw new Error(`invalid vote value ${vote}`);if(!this.#votes[voteId])throw new Error(`Nothing found for ${voteId}`);const ended=(new Date).getTime()>this.#votes[voteId].endTime;if(ended&&!this.#votes[voteId].finished&&this.#endVoting(voteId),ended)throw new Error("voting already ended");if(!this.#canVote())throw new Error("Not allowed to vote");await this.#beforeVote(),this.#votes[voteId][msg.sender]=vote,await this.#afterVote()}get votesInProgress(){return Object.entries(this.#votes).filter((([id,vote])=>!vote.finished)).map((([id,vote])=>({...vote,id:id})))}#disableVoting(){this.#votingDisabled=!0}disableVoting(){if(!this.#canVote())throw new Error("not a allowed");this.createVote("disable voting","Warning this disables all voting features forever",(new Date).getTime()+this.#votingDuration,"#disableVoting",[])}sync(){for(const vote of this.votesInProgress)vote.endTime<(new Date).getTime()&&this.#endVoting(vote.id)}}class PublicVoting extends Voting{constructor(state){super(state)}}class TokenReceiver extends PublicVoting{#tokenToReceive;#tokenAmountToReceive;#tokenReceiver;#voteType="transfer";constructor(tokenToReceive,tokenAmountToReceive,burns,state){super(state),state?(this.#tokenReceiver=state.tokenReceiver,this.#tokenToReceive=state.tokenToReceive,this.#tokenAmountToReceive=BigInt(state.tokenAmountToReceive),this.#voteType=state.voteType):(this.#tokenReceiver=msg.contract,this.#tokenToReceive=tokenToReceive,this.#tokenAmountToReceive=BigInt(tokenAmountToReceive),burns&&(this.#voteType="burn"))}get tokenToReceive(){return this.#tokenToReceive}get tokenAmountToReceive(){return this.#tokenAmountToReceive}get tokenReceiver(){return this.#tokenReceiver}get state(){return{...super.state,tokenReceiver:this.#tokenReceiver,tokenToReceive:this.#tokenToReceive,tokenAmountToReceive:this.#tokenAmountToReceive,voteType:this.#voteType}}async#canVote(){return await msg.staticCall(this.#tokenToReceive,"balanceOf",[msg.sender])>=this.#tokenAmountToReceive}async _canVote(){return this.#canVote()}async#beforeVote(){return"burn"===this.#voteType?msg.staticCall(this.tokenToReceive,"burn",[this.tokenAmountToReceive]):msg.staticCall(this.tokenToReceive,"transfer",[msg.sender,this.tokenReceiver,this.tokenAmountToReceive])}async _beforeVote(){return this.#beforeVote()}async _payTokenToReceive(){return msg.staticCall(this.#tokenToReceive,"transfer",[msg.sender,this.#tokenReceiver,this.#tokenAmountToReceive])}async _burnTokenToReceive(){return msg.staticCall(this.#tokenToReceive,"burn",[this.#tokenAmountToReceive])}async _canPay(){return(await msg.call(this.#tokenToReceive,"balance",[])).gte(this.tokenAmountToReceive)}#changeTokenToReceive(address){this.#tokenToReceive=address}#changeTokenAmountToReceive(amount){this.#tokenAmountToReceive=amount}#changeVoteType(type){this.#voteType=type}#getTokensOut(amount,receiver){return msg.call(this.#tokenReceiver,"transfer",[this.#tokenReceiver,receiver,amount])}async changeVoteType(type){if(!this.#canVote())throw new Error("not a allowed");if("transfer"===this.#voteType&&await this.#balance()>0n)throw new Error("get tokens out first or they be lost forever");this.createVote("change the token amount to receive","set tokenAmountToReceive",(new Date).getTime()+this.votingDuration,"#changeVoteType",[type])}getTokensOut(amount,receiver){if(!this.#canVote())throw new Error("not a allowed");this.createVote("withdraw all tokens",`withdraw all tokens to ${receiver}`,(new Date).getTime()+this.votingDuration,"#getTokensOut",[amount,receiver])}changeTokenAmountToReceive(){if(!this.#canVote())throw new Error("not a allowed");this.createVote("change the token amount to receive","set tokenAmountToReceive",(new Date).getTime()+this.votingDuration,"#changeTokenAmountToReceive",[])}#balance(){return msg.staticCall(this.#tokenToReceive,"balanceOf",[this.#tokenReceiver])}async changeTokenToReceive(){if(!this.#canVote())throw new Error("not a allowed");if(await this.#balance()>0n&&"transfer"===this.#voteType)throw new Error("get tokens out first or they be lost forever");this.createVote("change the token to receive","set tokenToReceive to a new address",(new Date).getTime()+this.votingDuration,"#changeTokenToReceive",[])}}class Factory extends TokenReceiver{#name="LeofcoinContractFactory";#totalContracts=BigInt(0);#contracts=[];constructor(tokenToReceive,tokenAmountToReceive,state){super(tokenToReceive,tokenAmountToReceive,!0,state),state&&(this.#contracts=state.contracts,this.#totalContracts=state.totalContracts)}get state(){return{...super.state,totalContracts:this.#totalContracts,contracts:this.#contracts}}get name(){return this.#name}get contracts(){return[...this.#contracts]}get totalContracts(){return this.#totalContracts}isRegistered(address){return this.#contracts.includes(address)}#isCreator(address){return msg.staticCall(address,"_isContractCreator")}async registerContract(address){if(!this._canPay())throw new Error("can't register, balance to low");if(!await this.#isCreator(address))throw new Error("You don't own that contract");if(this.#contracts.includes(address))throw new Error("already registered");await this._payTokenToReceive(),this.#totalContracts+=1n,this.#contracts.push(address)}}export{Factory as default};
|
|
@@ -14,7 +14,7 @@ export default class NameService extends TokenReceiver {
|
|
|
14
14
|
get name(): string;
|
|
15
15
|
get registry(): {};
|
|
16
16
|
get state(): NameServiceState;
|
|
17
|
-
constructor(factoryAddress: address, tokenToReceive: address, validatorAddress: address, tokenAmountToReceive:
|
|
17
|
+
constructor(factoryAddress: address, tokenToReceive: address, validatorAddress: address, tokenAmountToReceive: bigint, state: NameServiceState);
|
|
18
18
|
purchaseName(name: string | number, address: any): Promise<void>;
|
|
19
19
|
lookup(name: string | number): any;
|
|
20
20
|
transferOwnership(name: string | number, to: any): void;
|
package/exports/name-service.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Voting extends ContractCreator{#votes={};#votingDisabled=!1;#votingDuration=1728e5;constructor(state){super(state),state&&(this.#votes=state.votes,this.#votingDisabled=state.votingDisabled,this.#votingDuration=state.votingDuration)}get votes(){return{...this.#votes}}get votingDuration(){return this.#votingDuration}get votingDisabled(){return this.#votingDisabled}get state(){return{...super.state,votes:this.#votes,votingDisabled:this.#votingDisabled,votingDuration:this.#votingDuration}}#canVote(){return this._canVote?.()}#beforeVote(){return this._beforeVote?.()}#afterVote(){return this._afterVote?.()}createVote(title,description,endTime,method,args=[]){if(!this.#canVote())throw new Error("Not allowed to create a vote");const id=crypto.randomUUID();this.#votes[id]={title:title,description:description,method:method,endTime:endTime,args:args}}#endVoting(voteId){let agree=Object.values(this.#votes[voteId].results).filter((result=>1===result)),disagree=Object.values(this.#votes[voteId].results).filter((result=>0===result));agree.length>disagree.length&&this[this.#votes[voteId].method](...this.#votes[voteId].args),this.#votes[voteId].finished=!0}async vote(voteId,vote){if(0!==(vote=Number(vote))&&.5!==vote&&1!==vote)throw new Error(`invalid vote value ${vote}`);if(!this.#votes[voteId])throw new Error(`Nothing found for ${voteId}`);const ended=(new Date).getTime()>this.#votes[voteId].endTime;if(ended&&!this.#votes[voteId].finished&&this.#endVoting(voteId),ended)throw new Error("voting already ended");if(!this.#canVote())throw new Error("Not allowed to vote");await this.#beforeVote(),this.#votes[voteId][msg.sender]=vote,await this.#afterVote()}get votesInProgress(){return Object.entries(this.#votes).filter((([id,vote])=>!vote.finished)).map((([id,vote])=>({...vote,id:id})))}#disableVoting(){this.#votingDisabled=!0}disableVoting(){if(!this.#canVote())throw new Error("not a allowed");this.createVote("disable voting","Warning this disables all voting features forever",(new Date).getTime()+this.#votingDuration,"#disableVoting",[])}sync(){for(const vote of this.votesInProgress)vote.endTime<(new Date).getTime()&&this.#endVoting(vote.id)}}class PublicVoting extends Voting{constructor(state){super(state)}}class TokenReceiver extends PublicVoting{#tokenToReceive;#tokenAmountToReceive;#tokenReceiver;#voteType="transfer";constructor(tokenToReceive,tokenAmountToReceive,burns,state){super(state),state?(this.#tokenReceiver=state.tokenReceiver,this.#tokenToReceive=state.tokenToReceive,this.#tokenAmountToReceive=
|
|
1
|
+
class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Voting extends ContractCreator{#votes={};#votingDisabled=!1;#votingDuration=1728e5;constructor(state){super(state),state&&(this.#votes=state.votes,this.#votingDisabled=state.votingDisabled,this.#votingDuration=state.votingDuration)}get votes(){return{...this.#votes}}get votingDuration(){return this.#votingDuration}get votingDisabled(){return this.#votingDisabled}get state(){return{...super.state,votes:this.#votes,votingDisabled:this.#votingDisabled,votingDuration:this.#votingDuration}}#canVote(){return this._canVote?.()}#beforeVote(){return this._beforeVote?.()}#afterVote(){return this._afterVote?.()}createVote(title,description,endTime,method,args=[]){if(!this.#canVote())throw new Error("Not allowed to create a vote");const id=crypto.randomUUID();this.#votes[id]={title:title,description:description,method:method,endTime:endTime,args:args}}#endVoting(voteId){let agree=Object.values(this.#votes[voteId].results).filter((result=>1===result)),disagree=Object.values(this.#votes[voteId].results).filter((result=>0===result));agree.length>disagree.length&&this[this.#votes[voteId].method](...this.#votes[voteId].args),this.#votes[voteId].finished=!0}async vote(voteId,vote){if(0!==(vote=Number(vote))&&.5!==vote&&1!==vote)throw new Error(`invalid vote value ${vote}`);if(!this.#votes[voteId])throw new Error(`Nothing found for ${voteId}`);const ended=(new Date).getTime()>this.#votes[voteId].endTime;if(ended&&!this.#votes[voteId].finished&&this.#endVoting(voteId),ended)throw new Error("voting already ended");if(!this.#canVote())throw new Error("Not allowed to vote");await this.#beforeVote(),this.#votes[voteId][msg.sender]=vote,await this.#afterVote()}get votesInProgress(){return Object.entries(this.#votes).filter((([id,vote])=>!vote.finished)).map((([id,vote])=>({...vote,id:id})))}#disableVoting(){this.#votingDisabled=!0}disableVoting(){if(!this.#canVote())throw new Error("not a allowed");this.createVote("disable voting","Warning this disables all voting features forever",(new Date).getTime()+this.#votingDuration,"#disableVoting",[])}sync(){for(const vote of this.votesInProgress)vote.endTime<(new Date).getTime()&&this.#endVoting(vote.id)}}class PublicVoting extends Voting{constructor(state){super(state)}}class TokenReceiver extends PublicVoting{#tokenToReceive;#tokenAmountToReceive;#tokenReceiver;#voteType="transfer";constructor(tokenToReceive,tokenAmountToReceive,burns,state){super(state),state?(this.#tokenReceiver=state.tokenReceiver,this.#tokenToReceive=state.tokenToReceive,this.#tokenAmountToReceive=BigInt(state.tokenAmountToReceive),this.#voteType=state.voteType):(this.#tokenReceiver=msg.contract,this.#tokenToReceive=tokenToReceive,this.#tokenAmountToReceive=BigInt(tokenAmountToReceive),burns&&(this.#voteType="burn"))}get tokenToReceive(){return this.#tokenToReceive}get tokenAmountToReceive(){return this.#tokenAmountToReceive}get tokenReceiver(){return this.#tokenReceiver}get state(){return{...super.state,tokenReceiver:this.#tokenReceiver,tokenToReceive:this.#tokenToReceive,tokenAmountToReceive:this.#tokenAmountToReceive,voteType:this.#voteType}}async#canVote(){return await msg.staticCall(this.#tokenToReceive,"balanceOf",[msg.sender])>=this.#tokenAmountToReceive}async _canVote(){return this.#canVote()}async#beforeVote(){return"burn"===this.#voteType?msg.staticCall(this.tokenToReceive,"burn",[this.tokenAmountToReceive]):msg.staticCall(this.tokenToReceive,"transfer",[msg.sender,this.tokenReceiver,this.tokenAmountToReceive])}async _beforeVote(){return this.#beforeVote()}async _payTokenToReceive(){return msg.staticCall(this.#tokenToReceive,"transfer",[msg.sender,this.#tokenReceiver,this.#tokenAmountToReceive])}async _burnTokenToReceive(){return msg.staticCall(this.#tokenToReceive,"burn",[this.#tokenAmountToReceive])}async _canPay(){return(await msg.call(this.#tokenToReceive,"balance",[])).gte(this.tokenAmountToReceive)}#changeTokenToReceive(address){this.#tokenToReceive=address}#changeTokenAmountToReceive(amount){this.#tokenAmountToReceive=amount}#changeVoteType(type){this.#voteType=type}#getTokensOut(amount,receiver){return msg.call(this.#tokenReceiver,"transfer",[this.#tokenReceiver,receiver,amount])}async changeVoteType(type){if(!this.#canVote())throw new Error("not a allowed");if("transfer"===this.#voteType&&await this.#balance()>0n)throw new Error("get tokens out first or they be lost forever");this.createVote("change the token amount to receive","set tokenAmountToReceive",(new Date).getTime()+this.votingDuration,"#changeVoteType",[type])}getTokensOut(amount,receiver){if(!this.#canVote())throw new Error("not a allowed");this.createVote("withdraw all tokens",`withdraw all tokens to ${receiver}`,(new Date).getTime()+this.votingDuration,"#getTokensOut",[amount,receiver])}changeTokenAmountToReceive(){if(!this.#canVote())throw new Error("not a allowed");this.createVote("change the token amount to receive","set tokenAmountToReceive",(new Date).getTime()+this.votingDuration,"#changeTokenAmountToReceive",[])}#balance(){return msg.staticCall(this.#tokenToReceive,"balanceOf",[this.#tokenReceiver])}async changeTokenToReceive(){if(!this.#canVote())throw new Error("not a allowed");if(await this.#balance()>0n&&"transfer"===this.#voteType)throw new Error("get tokens out first or they be lost forever");this.createVote("change the token to receive","set tokenToReceive to a new address",(new Date).getTime()+this.votingDuration,"#changeTokenToReceive",[])}}class NameService extends TokenReceiver{#name="LeofcoinNameService";#registry={};get name(){return this.#name}get registry(){return{...this.#registry}}get state(){return{...super.state,registry:this.#registry}}constructor(factoryAddress,tokenToReceive,validatorAddress,tokenAmountToReceive,state){super(tokenToReceive,tokenAmountToReceive,!0,state),state?this.#registry=state.registry:(this.#registry.LeofcoinContractFactory={owner:msg.sender,address:factoryAddress},this.#registry.LeofcoinToken={owner:msg.sender,address:tokenToReceive},this.#registry.LeofcoinValidators={owner:msg.sender,address:validatorAddress})}async purchaseName(name,address){await this._canPay(),await this._payTokenToReceive(),this.#registry[name]={owner:msg.sender,address:address}}lookup(name){return this.#registry[name]}transferOwnership(name,to){if(msg.sender!==this.#registry[name].owner)throw new Error("not allowed");this.#registry[name].owner=to}changeAddress(name,address){if(msg.sender!==this.#registry[name].owner)throw new Error("not allowed");this.#registry[name].address=address}}export{NameService as default};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { IToken } from '@leofcoin/standards/interfaces/i-token';
|
|
1
2
|
import Token, { TokenState } from '@leofcoin/standards/token.js';
|
|
2
|
-
export default class Leofcoin extends Token {
|
|
3
|
+
export default class Leofcoin extends Token implements IToken {
|
|
3
4
|
constructor(state: TokenState);
|
|
4
5
|
}
|
package/exports/native-token.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Roles extends ContractCreator{#roles={OWNER:[],MINT:[],BURN:[]};constructor(state){if(super(state),state?.roles){if(!(state.roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...state.roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER")}get state(){return{...super.state,roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}class Token extends Roles{#name;#symbol;#holders=
|
|
1
|
+
class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Roles extends ContractCreator{#roles={OWNER:[],MINT:[],BURN:[]};constructor(state){if(super(state),state?.roles){if(!(state.roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...state.roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER")}get state(){return{...super.state,roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}class Token extends Roles{#name;#symbol;#holders=BigInt(0);#balances={};#approvals={};#decimals=18;#totalSupply=BigInt(0);#maxSupply=BigInt(0);#stakingContract;constructor(name,symbol,decimals=18,state){if(!name)throw new Error("name undefined");if(!symbol)throw new Error("symbol undefined");super(state),state?(this.#balances=(balances=>{const _balances={};for(const address in balances)_balances[address]=BigInt(balances[address]);return _balances})(state.balances),this.#approvals=(approvals=>{const _approvals={};for(const owner in approvals){_approvals[owner]={};for(const operator in approvals[owner])_approvals[owner][operator]=BigInt(approvals[owner][operator])}return _approvals})(state.approvals),this.#holders=BigInt(state.holders),this.#totalSupply=BigInt(state.totalSupply),this.#name=name,this.#symbol=symbol,this.#decimals=decimals,this.#maxSupply=BigInt(state.maxSupply)):(this.#name=name,this.#symbol=symbol,this.#decimals=decimals)}get state(){return{...super.state,name:this.#name,symbol:this.#symbol,decimals:this.#decimals,holders:this.holders,balances:this.balances,approvals:{...this.#approvals},totalSupply:this.totalSupply,maxSupply:this.#maxSupply}}get maxSupply(){return this.#maxSupply}get totalSupply(){return this.#totalSupply}get name(){return this.#name}get symbol(){return this.#symbol}get holders(){return this.#holders}get balances(){return{...this.#balances}}get approvals(){return this.#approvals}get decimals(){return this.#decimals}mint(to,amount){if(!this.hasRole(msg.sender,"MINT"))throw new Error("mint role required");const supply=this.#totalSupply+amount;if(0n===this.#maxSupply)this.#totalSupply=supply,this.#increaseBalance(to,amount);else{if(!(supply<=this.#maxSupply))throw new Error("amount exceeds max supply");this.#totalSupply=supply,this.#increaseBalance(to,amount)}}burn(from,amount){if(!this.hasRole(msg.sender,"BURN")&&msg.sender!==from)throw new Error("not the owner or burn role required");if(this.#balances[from]<amount)throw new Error("amount exceeds balance");const total=this.#totalSupply-amount;if(!(total>=0))throw new Error("amount exceeds total supply");this.#totalSupply=total,this.#decreaseBalance(from,amount)}#beforeTransfer(from,to,amount){if(!this.#balances[from]||this.#balances[from]<amount)throw new Error("amount exceeds balance")}#updateHolders(address,previousBalance){0n===this.#balances[address]?this.#holders-=1n:0n!==this.#balances[address]&&0n===previousBalance&&(this.#holders+=1n)}#increaseBalance(address,amount){this.#balances[address]||(this.#balances[address]=BigInt(0));const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address]+=amount,this.#updateHolders(address,previousBalance)}#decreaseBalance(address,amount){const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address]-=amount,this.#updateHolders(address,previousBalance)}balance(){return this.#balances[msg.sender]}balanceOf(address){return this.#balances[address]}setApproval(operator,amount){const owner=msg.sender;this.#approvals[owner]||(this.#approvals[owner]={}),this.#approvals[owner][operator]=BigInt(amount)}approved(owner,operator,amount){return this.#approvals[owner][operator]===amount}transfer(from,to,amount){amount=BigInt(amount),this.#beforeTransfer(from,to,amount),this.#decreaseBalance(from,amount),this.#increaseBalance(to,amount)}}class Leofcoin extends Token{constructor(state){super("Leofcoin","LFC",18,state)}}export{Leofcoin as default};
|
package/exports/power-token.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { IToken } from '@leofcoin/standards/interfaces/i-token';
|
|
1
2
|
import Token, { TokenState } from '@leofcoin/standards/token.js';
|
|
2
|
-
export default class Power extends Token {
|
|
3
|
+
export default class Power extends Token implements IToken {
|
|
3
4
|
constructor(state: TokenState);
|
|
4
5
|
}
|
package/exports/power-token.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Roles extends ContractCreator{#roles={OWNER:[],MINT:[],BURN:[]};constructor(state){if(super(state),state?.roles){if(!(state.roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...state.roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER")}get state(){return{...super.state,roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}class Token extends Roles{#name;#symbol;#holders=
|
|
1
|
+
class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Roles extends ContractCreator{#roles={OWNER:[],MINT:[],BURN:[]};constructor(state){if(super(state),state?.roles){if(!(state.roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...state.roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER")}get state(){return{...super.state,roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}class Token extends Roles{#name;#symbol;#holders=BigInt(0);#balances={};#approvals={};#decimals=18;#totalSupply=BigInt(0);#maxSupply=BigInt(0);#stakingContract;constructor(name,symbol,decimals=18,state){if(!name)throw new Error("name undefined");if(!symbol)throw new Error("symbol undefined");super(state),state?(this.#balances=(balances=>{const _balances={};for(const address in balances)_balances[address]=BigInt(balances[address]);return _balances})(state.balances),this.#approvals=(approvals=>{const _approvals={};for(const owner in approvals){_approvals[owner]={};for(const operator in approvals[owner])_approvals[owner][operator]=BigInt(approvals[owner][operator])}return _approvals})(state.approvals),this.#holders=BigInt(state.holders),this.#totalSupply=BigInt(state.totalSupply),this.#name=name,this.#symbol=symbol,this.#decimals=decimals,this.#maxSupply=BigInt(state.maxSupply)):(this.#name=name,this.#symbol=symbol,this.#decimals=decimals)}get state(){return{...super.state,name:this.#name,symbol:this.#symbol,decimals:this.#decimals,holders:this.holders,balances:this.balances,approvals:{...this.#approvals},totalSupply:this.totalSupply,maxSupply:this.#maxSupply}}get maxSupply(){return this.#maxSupply}get totalSupply(){return this.#totalSupply}get name(){return this.#name}get symbol(){return this.#symbol}get holders(){return this.#holders}get balances(){return{...this.#balances}}get approvals(){return this.#approvals}get decimals(){return this.#decimals}mint(to,amount){if(!this.hasRole(msg.sender,"MINT"))throw new Error("mint role required");const supply=this.#totalSupply+amount;if(0n===this.#maxSupply)this.#totalSupply=supply,this.#increaseBalance(to,amount);else{if(!(supply<=this.#maxSupply))throw new Error("amount exceeds max supply");this.#totalSupply=supply,this.#increaseBalance(to,amount)}}burn(from,amount){if(!this.hasRole(msg.sender,"BURN")&&msg.sender!==from)throw new Error("not the owner or burn role required");if(this.#balances[from]<amount)throw new Error("amount exceeds balance");const total=this.#totalSupply-amount;if(!(total>=0))throw new Error("amount exceeds total supply");this.#totalSupply=total,this.#decreaseBalance(from,amount)}#beforeTransfer(from,to,amount){if(!this.#balances[from]||this.#balances[from]<amount)throw new Error("amount exceeds balance")}#updateHolders(address,previousBalance){0n===this.#balances[address]?this.#holders-=1n:0n!==this.#balances[address]&&0n===previousBalance&&(this.#holders+=1n)}#increaseBalance(address,amount){this.#balances[address]||(this.#balances[address]=BigInt(0));const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address]+=amount,this.#updateHolders(address,previousBalance)}#decreaseBalance(address,amount){const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address]-=amount,this.#updateHolders(address,previousBalance)}balance(){return this.#balances[msg.sender]}balanceOf(address){return this.#balances[address]}setApproval(operator,amount){const owner=msg.sender;this.#approvals[owner]||(this.#approvals[owner]={}),this.#approvals[owner][operator]=BigInt(amount)}approved(owner,operator,amount){return this.#approvals[owner][operator]===amount}transfer(from,to,amount){amount=BigInt(amount),this.#beforeTransfer(from,to,amount),this.#decreaseBalance(from,amount),this.#increaseBalance(to,amount)}}class Power extends Token{constructor(state){super("Power","PWR",18,state)}}export{Power as default};
|
package/exports/src/factory.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
/// <reference types="@leofcoin/types/global" />
|
|
1
2
|
import { TokenReceiver } from '@leofcoin/standards';
|
|
2
3
|
import type { PublicVotingState } from '@leofcoin/standards/public-voting';
|
|
3
4
|
import { TokenReceiverState } from '@leofcoin/standards/token-receiver';
|
|
4
5
|
export interface FactoryState extends TokenReceiverState {
|
|
5
6
|
contracts: any[];
|
|
6
|
-
totalContracts:
|
|
7
|
+
totalContracts: bigint;
|
|
7
8
|
}
|
|
8
9
|
export default class Factory extends TokenReceiver {
|
|
9
10
|
#private;
|
|
10
|
-
constructor(tokenToReceive: address, tokenAmountToReceive:
|
|
11
|
+
constructor(tokenToReceive: address, tokenAmountToReceive: bigint, state: FactoryState);
|
|
11
12
|
get state(): PublicVotingState;
|
|
12
13
|
get name(): string;
|
|
13
14
|
get contracts(): string[];
|
|
14
|
-
get totalContracts():
|
|
15
|
+
get totalContracts(): bigint;
|
|
15
16
|
isRegistered(address: any): boolean;
|
|
16
17
|
/**
|
|
17
18
|
*
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="@leofcoin/types/global" />
|
|
1
2
|
import { TokenReceiver } from '@leofcoin/standards';
|
|
2
3
|
import { TokenReceiverState } from '@leofcoin/standards/token-receiver';
|
|
3
4
|
type registry = {
|
|
@@ -14,7 +15,7 @@ export default class NameService extends TokenReceiver {
|
|
|
14
15
|
get name(): string;
|
|
15
16
|
get registry(): {};
|
|
16
17
|
get state(): NameServiceState;
|
|
17
|
-
constructor(factoryAddress: address, tokenToReceive: address, validatorAddress: address, tokenAmountToReceive:
|
|
18
|
+
constructor(factoryAddress: address, tokenToReceive: address, validatorAddress: address, tokenAmountToReceive: bigint, state: NameServiceState);
|
|
18
19
|
purchaseName(name: string | number, address: any): Promise<void>;
|
|
19
20
|
lookup(name: string | number): any;
|
|
20
21
|
transferOwnership(name: string | number, to: any): void;
|
|
@@ -1,21 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="@leofcoin/types/global" />
|
|
2
|
+
import Roles, { RolesState } from '@leofcoin/standards/roles.js';
|
|
3
|
+
export declare interface ValidatorsState extends RolesState {
|
|
4
|
+
balances: {
|
|
5
|
+
[address: string]: bigint;
|
|
6
|
+
};
|
|
7
|
+
minimumBalance: bigint;
|
|
8
|
+
currency: address;
|
|
9
|
+
validators: address[];
|
|
10
|
+
currentValidator: address;
|
|
11
|
+
}
|
|
2
12
|
export default class Validators extends Roles {
|
|
3
13
|
#private;
|
|
4
14
|
get state(): {
|
|
5
|
-
|
|
15
|
+
balances: {
|
|
16
|
+
[address: string]: bigint;
|
|
17
|
+
};
|
|
18
|
+
minimumBalance: bigint;
|
|
6
19
|
currency: string;
|
|
7
20
|
validators: string[];
|
|
21
|
+
currentValidator: string;
|
|
8
22
|
roles: {
|
|
9
23
|
[index: string]: string[];
|
|
10
24
|
};
|
|
11
25
|
contractCreator: string;
|
|
12
26
|
};
|
|
13
|
-
constructor(tokenAddress: address, state:
|
|
27
|
+
constructor(tokenAddress: address, state: ValidatorsState);
|
|
28
|
+
get currentValidator(): string;
|
|
14
29
|
get name(): string;
|
|
15
30
|
get currency(): string;
|
|
16
31
|
get validators(): string[];
|
|
17
32
|
get totalValidators(): number;
|
|
18
|
-
get minimumBalance():
|
|
33
|
+
get minimumBalance(): bigint;
|
|
19
34
|
changeCurrency(currency: any): void;
|
|
20
35
|
has(validator: any): boolean;
|
|
21
36
|
addValidator(validator: address): Promise<void>;
|
package/exports/validators.d.ts
CHANGED
|
@@ -1,23 +1,38 @@
|
|
|
1
|
-
import Roles from '@leofcoin/standards/roles.js';
|
|
1
|
+
import Roles, { RolesState } from '@leofcoin/standards/roles.js';
|
|
2
|
+
export declare interface ValidatorsState extends RolesState {
|
|
3
|
+
balances: {
|
|
4
|
+
[address: string]: bigint;
|
|
5
|
+
};
|
|
6
|
+
minimumBalance: bigint;
|
|
7
|
+
currency: address;
|
|
8
|
+
validators: address[];
|
|
9
|
+
currentValidator: address;
|
|
10
|
+
}
|
|
2
11
|
export default class Validators extends Roles {
|
|
3
12
|
#private;
|
|
4
13
|
get state(): {
|
|
5
|
-
|
|
14
|
+
balances: {
|
|
15
|
+
[address: string]: bigint;
|
|
16
|
+
};
|
|
17
|
+
minimumBalance: bigint;
|
|
6
18
|
currency: string;
|
|
7
19
|
validators: string[];
|
|
20
|
+
currentValidator: string;
|
|
8
21
|
roles: {
|
|
9
|
-
[index: string]:
|
|
22
|
+
[index: string]: address[];
|
|
10
23
|
};
|
|
11
|
-
contractCreator:
|
|
24
|
+
contractCreator: address;
|
|
12
25
|
};
|
|
13
|
-
constructor(tokenAddress: address, state:
|
|
26
|
+
constructor(tokenAddress: address, state: ValidatorsState);
|
|
27
|
+
get currentValidator(): string;
|
|
14
28
|
get name(): string;
|
|
15
29
|
get currency(): string;
|
|
16
30
|
get validators(): string[];
|
|
17
31
|
get totalValidators(): number;
|
|
18
|
-
get minimumBalance():
|
|
32
|
+
get minimumBalance(): bigint;
|
|
19
33
|
changeCurrency(currency: any): void;
|
|
20
34
|
has(validator: any): boolean;
|
|
21
35
|
addValidator(validator: address): Promise<void>;
|
|
22
|
-
removeValidator(validator: any): void
|
|
36
|
+
removeValidator(validator: any): Promise<void>;
|
|
37
|
+
shuffleValidator(): void;
|
|
23
38
|
}
|
package/exports/validators.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Roles extends ContractCreator{#roles={OWNER:[],MINT:[],BURN:[]};constructor(state){if(super(state),state?.roles){if(!(state.roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...state.roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER")}get state(){return{...super.state,roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}
|
|
1
|
+
const between=(min,max,length=1)=>{let arr=[];for(let i=0;i<length;++i)arr=[...arr,Math.floor(Math.random()*(max+1-min)+min)];return arr},lottery=(numbers=7,max=100,min=0,length=100)=>{let arr=[],ran=between(min,max,length);ran=(arr=>arr.filter(((el,pos,arr)=>arr.indexOf(el)==pos)))(ran);for(let i=0;i<numbers;++i){const _ran=between(min,ran.length-1,ran.length)[0];arr=[...arr,ran[_ran]]}return arr};class ContractCreator{#creator;constructor(state){this.#creator=state?state.contractCreator:msg.sender}get _contractCreator(){return this.#creator}get state(){return{contractCreator:this.#creator}}get _isContractCreator(){return msg.sender===this.#creator}}class Roles extends ContractCreator{#roles={OWNER:[],MINT:[],BURN:[]};constructor(state){if(super(state),state?.roles){if(!(state.roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...state.roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER")}get state(){return{...super.state,roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}class Validators extends Roles{#name="LeofcoinValidators";#validators=[];#currentValidator;#currency;#minimumBalance=BigInt(5e4);#balances={};get state(){return{...super.state,balances:this.#balances,minimumBalance:this.#minimumBalance,currency:this.#currency,validators:this.#validators,currentValidator:this.#currentValidator}}constructor(tokenAddress,state){super(state?.roles),state?(this.#minimumBalance=BigInt(state.minimumBalance),this.#currency=state.currency,this.#validators=state.validators,this.#balances=state.balances,this.#currentValidator=state.currentValidator):(this.#currency=tokenAddress,this.#validators.push(msg.sender),this.#currentValidator=msg.sender)}get currentValidator(){return this.#currentValidator}get name(){return this.#name}get currency(){return this.#currency}get validators(){return this.#validators}get totalValidators(){return this.#validators.length}get minimumBalance(){return this.#minimumBalance}changeCurrency(currency){if(!this.hasRole(msg.sender,"OWNER"))throw new Error("not an owner");this.#currency=currency}has(validator){return this.#validators.includes(validator)}#isAllowed(address){if(msg.sender!==address&&!this.hasRole(msg.sender,"OWNER"))throw new Error("sender is not the validator or owner");return!0}async addValidator(validator){if(this.#isAllowed(validator),this.has(validator))throw new Error("validator already exists");const balance=await msg.staticCall(this.currency,"balanceOf",[validator]);if(this.minimumBalance>balance)throw new Error(`balance to low! got: ${balance} need: ${this.#minimumBalance}`);await msg.call(this.currency,"transfer",[validator,msg.contract,this.#minimumBalance]),this.#balances[validator]=this.#minimumBalance,this.#validators.push(validator)}async removeValidator(validator){if(this.#isAllowed(validator),!this.has(validator))throw new Error("validator not found");await msg.call(this.currency,"transfer",[msg.contract,validator,this.#minimumBalance]),delete this.#balances[validator],this.#validators.splice(this.#validators.indexOf(validator),1)}shuffleValidator(){const _peers=state.peers,peers=_peers.filter((peer=>this.#validators.includes(peer[0]))).map((peer=>(peer[1].totalBytes=peer[1].bw.up+peer[1].bw.down,peer))).sort(((a,b)=>b[1].totalBytes-a[1].totalBytes)).splice(0,_peers.length>128?128:_peers.length);let nextValidator=peers[lottery(1,peers.length-1)[0]][0];if(this.#currentValidator===nextValidator&&1!==peers.length){nextValidator=peers[lottery(1,peers.length-1)[0]][0]}this.#currentValidator=nextValidator}}export{Validators as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leofcoin/contracts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "rollup -c",
|
|
15
|
-
"test": "
|
|
15
|
+
"test": "mocha test/**/*.js"
|
|
16
16
|
},
|
|
17
17
|
"repository": {
|
|
18
18
|
"type": "git",
|
|
@@ -26,16 +26,18 @@
|
|
|
26
26
|
},
|
|
27
27
|
"homepage": "https://github.com/leofcoin/contracts#readme",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@leofcoin/
|
|
30
|
-
"
|
|
31
|
-
"lucky-numbers": "^1.2.0"
|
|
29
|
+
"@leofcoin/standards": "^0.2.11",
|
|
30
|
+
"lucky-numbers": "^1.2.1"
|
|
32
31
|
},
|
|
33
32
|
"devDependencies": {
|
|
34
|
-
"@
|
|
35
|
-
"@rollup/plugin-node-resolve": "^15.
|
|
36
|
-
"@rollup/plugin-terser": "^0.4.
|
|
37
|
-
"@rollup/plugin-typescript": "^11.
|
|
38
|
-
"
|
|
39
|
-
"
|
|
33
|
+
"@leofcoin/types": "^1.0.17",
|
|
34
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
35
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
36
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
37
|
+
"chai": "^5.1.1",
|
|
38
|
+
"chai-as-promised": "^8.0.0",
|
|
39
|
+
"mocha": "^10.7.3",
|
|
40
|
+
"rollup": "^4.22.2",
|
|
41
|
+
"tslib": "^2.7.0"
|
|
40
42
|
}
|
|
41
43
|
}
|
package/src/factory.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { TokenReceiverState } from '@leofcoin/standards/token-receiver'
|
|
|
4
4
|
|
|
5
5
|
export interface FactoryState extends TokenReceiverState {
|
|
6
6
|
contracts: any[]
|
|
7
|
-
totalContracts:
|
|
7
|
+
totalContracts: bigint
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export default class Factory extends TokenReceiver {
|
|
@@ -15,13 +15,13 @@ export default class Factory extends TokenReceiver {
|
|
|
15
15
|
/**
|
|
16
16
|
* uint
|
|
17
17
|
*/
|
|
18
|
-
#totalContracts:
|
|
18
|
+
#totalContracts: bigint = BigInt(0)
|
|
19
19
|
/**
|
|
20
20
|
* Array => string
|
|
21
21
|
*/
|
|
22
22
|
#contracts: address[] = []
|
|
23
23
|
|
|
24
|
-
constructor(tokenToReceive: address, tokenAmountToReceive:
|
|
24
|
+
constructor(tokenToReceive: address, tokenAmountToReceive: bigint, state: FactoryState) {
|
|
25
25
|
super(tokenToReceive, tokenAmountToReceive, true, state as TokenReceiverState)
|
|
26
26
|
if (state) {
|
|
27
27
|
this.#contracts = state.contracts
|
|
@@ -67,7 +67,7 @@ export default class Factory extends TokenReceiver {
|
|
|
67
67
|
if (!(await this.#isCreator(address))) throw new Error(`You don't own that contract`)
|
|
68
68
|
if (this.#contracts.includes(address)) throw new Error('already registered')
|
|
69
69
|
await this._payTokenToReceive()
|
|
70
|
-
this.#totalContracts
|
|
70
|
+
this.#totalContracts += 1n
|
|
71
71
|
this.#contracts.push(address)
|
|
72
72
|
}
|
|
73
73
|
}
|
package/src/name-service.ts
CHANGED
|
@@ -42,7 +42,7 @@ export default class NameService extends TokenReceiver {
|
|
|
42
42
|
factoryAddress: address,
|
|
43
43
|
tokenToReceive: address,
|
|
44
44
|
validatorAddress: address,
|
|
45
|
-
tokenAmountToReceive:
|
|
45
|
+
tokenAmountToReceive: bigint,
|
|
46
46
|
state: NameServiceState
|
|
47
47
|
) {
|
|
48
48
|
super(tokenToReceive, tokenAmountToReceive, true, state as TokenReceiverState)
|
package/src/native-token.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { IToken } from '@leofcoin/standards/interfaces/i-token'
|
|
2
|
+
import Token, { TokenState } from '@leofcoin/standards/token.js'
|
|
2
3
|
|
|
3
|
-
export default class Leofcoin extends Token {
|
|
4
|
+
export default class Leofcoin extends Token implements IToken {
|
|
4
5
|
constructor(state: TokenState) {
|
|
5
|
-
super('Leofcoin', 'LFC', 18, state)
|
|
6
|
+
super('Leofcoin', 'LFC', 18, state)
|
|
6
7
|
}
|
|
7
8
|
}
|
package/src/power-token.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { IToken } from '@leofcoin/standards/interfaces/i-token'
|
|
2
|
+
import Token, { TokenState } from '@leofcoin/standards/token.js'
|
|
2
3
|
|
|
3
|
-
export default class Power extends Token {
|
|
4
|
+
export default class Power extends Token implements IToken {
|
|
4
5
|
constructor(state: TokenState) {
|
|
5
|
-
super('Power', 'PWR', 18, state)
|
|
6
|
+
super('Power', 'PWR', 18, state)
|
|
6
7
|
}
|
|
7
8
|
}
|
package/src/validators.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import Roles from '@leofcoin/standards/roles.js'
|
|
2
1
|
import { lottery } from 'lucky-numbers'
|
|
2
|
+
import Roles, { RolesState } from '@leofcoin/standards/roles.js'
|
|
3
|
+
|
|
4
|
+
export declare interface ValidatorsState extends RolesState {
|
|
5
|
+
balances: { [address: string]: bigint }
|
|
6
|
+
minimumBalance: bigint
|
|
7
|
+
currency: address
|
|
8
|
+
validators: address[]
|
|
9
|
+
currentValidator: address
|
|
10
|
+
}
|
|
3
11
|
|
|
4
12
|
export default class Validators extends Roles {
|
|
5
13
|
/**
|
|
@@ -11,36 +19,44 @@ export default class Validators extends Roles {
|
|
|
11
19
|
*/
|
|
12
20
|
#validators: address[] = []
|
|
13
21
|
|
|
14
|
-
#currentValidator
|
|
22
|
+
#currentValidator: address
|
|
15
23
|
|
|
16
24
|
#currency: address
|
|
17
25
|
|
|
18
|
-
#minimumBalance:
|
|
26
|
+
#minimumBalance: bigint = BigInt(50_000)
|
|
19
27
|
|
|
20
|
-
#balances: { [address: address]:
|
|
28
|
+
#balances: { [address: address]: bigint } = {}
|
|
21
29
|
|
|
22
30
|
get state() {
|
|
23
31
|
return {
|
|
24
32
|
...super.state,
|
|
33
|
+
balances: this.#balances,
|
|
25
34
|
minimumBalance: this.#minimumBalance,
|
|
26
35
|
currency: this.#currency,
|
|
27
|
-
validators: this.#validators
|
|
36
|
+
validators: this.#validators,
|
|
37
|
+
currentValidator: this.#currentValidator
|
|
28
38
|
}
|
|
29
39
|
}
|
|
30
40
|
|
|
31
|
-
constructor(tokenAddress: address, state) {
|
|
41
|
+
constructor(tokenAddress: address, state: ValidatorsState) {
|
|
32
42
|
super(state?.roles)
|
|
33
43
|
if (state) {
|
|
34
|
-
this.#minimumBalance =
|
|
44
|
+
this.#minimumBalance = BigInt(state.minimumBalance)
|
|
35
45
|
this.#currency = state.currency
|
|
36
46
|
this.#validators = state.validators
|
|
47
|
+
this.#balances = state.balances
|
|
48
|
+
this.#currentValidator = state.currentValidator
|
|
37
49
|
} else {
|
|
38
|
-
this.#minimumBalance = BigNumber['from'](50_000)
|
|
39
50
|
this.#currency = tokenAddress
|
|
40
51
|
this.#validators.push(msg.sender)
|
|
52
|
+
this.#currentValidator = msg.sender
|
|
41
53
|
}
|
|
42
54
|
}
|
|
43
55
|
|
|
56
|
+
get currentValidator() {
|
|
57
|
+
return this.#currentValidator
|
|
58
|
+
}
|
|
59
|
+
|
|
44
60
|
get name() {
|
|
45
61
|
return this.#name
|
|
46
62
|
}
|
|
@@ -50,7 +66,7 @@ export default class Validators extends Roles {
|
|
|
50
66
|
}
|
|
51
67
|
|
|
52
68
|
get validators() {
|
|
53
|
-
return
|
|
69
|
+
return this.#validators
|
|
54
70
|
}
|
|
55
71
|
|
|
56
72
|
get totalValidators() {
|
|
@@ -78,14 +94,15 @@ export default class Validators extends Roles {
|
|
|
78
94
|
|
|
79
95
|
async addValidator(validator: address) {
|
|
80
96
|
this.#isAllowed(validator)
|
|
81
|
-
if (this.has(validator)) throw new Error('already
|
|
97
|
+
if (this.has(validator)) throw new Error('validator already exists')
|
|
82
98
|
|
|
83
99
|
const balance = await msg.staticCall(this.currency, 'balanceOf', [validator])
|
|
84
100
|
|
|
85
|
-
if (this.minimumBalance
|
|
101
|
+
if (this.minimumBalance > balance)
|
|
86
102
|
throw new Error(`balance to low! got: ${balance} need: ${this.#minimumBalance}`)
|
|
87
103
|
|
|
88
104
|
await msg.call(this.currency, 'transfer', [validator, msg.contract, this.#minimumBalance])
|
|
105
|
+
|
|
89
106
|
this.#balances[validator] = this.#minimumBalance
|
|
90
107
|
this.#validators.push(validator)
|
|
91
108
|
}
|
|
@@ -95,7 +112,7 @@ export default class Validators extends Roles {
|
|
|
95
112
|
if (!this.has(validator)) throw new Error('validator not found')
|
|
96
113
|
await msg.call(this.currency, 'transfer', [msg.contract, validator, this.#minimumBalance])
|
|
97
114
|
delete this.#balances[validator]
|
|
98
|
-
this.#validators.splice(this.#validators.indexOf(validator))
|
|
115
|
+
this.#validators.splice(this.#validators.indexOf(validator), 1)
|
|
99
116
|
}
|
|
100
117
|
|
|
101
118
|
shuffleValidator() {
|
|
@@ -103,10 +120,10 @@ export default class Validators extends Roles {
|
|
|
103
120
|
// select amount of peers to vote & pass when 2/3 select the same peer
|
|
104
121
|
// this.vote
|
|
105
122
|
// todo only ids should be accessable
|
|
106
|
-
const _peers =
|
|
123
|
+
const _peers = state.peers
|
|
107
124
|
const peers = _peers
|
|
108
125
|
// only validators make a chance
|
|
109
|
-
.filter((peer) => this.#validators
|
|
126
|
+
.filter((peer) => this.#validators.includes(peer[0]))
|
|
110
127
|
// add up the bytes
|
|
111
128
|
.map((peer) => {
|
|
112
129
|
peer[1].totalBytes = peer[1].bw.up + peer[1].bw.down
|
|
@@ -116,13 +133,14 @@ export default class Validators extends Roles {
|
|
|
116
133
|
// only return 128 best participating max
|
|
117
134
|
.splice(0, _peers.length > 128 ? 128 : _peers.length)
|
|
118
135
|
|
|
119
|
-
const luckyNumber = lottery(1, peers.length)
|
|
120
|
-
|
|
136
|
+
const luckyNumber = lottery(1, peers.length - 1)
|
|
137
|
+
|
|
138
|
+
let nextValidator = peers[luckyNumber[0]][0]
|
|
121
139
|
// redraw when the validator is the same
|
|
122
140
|
// but keep the net alive when only one validator is found
|
|
123
141
|
if (this.#currentValidator === nextValidator && peers.length !== 1) {
|
|
124
|
-
const luckyNumber = lottery(1, peers.length)
|
|
125
|
-
nextValidator =
|
|
142
|
+
const luckyNumber = lottery(1, peers.length - 1)
|
|
143
|
+
nextValidator = peers[luckyNumber[0]][0]
|
|
126
144
|
}
|
|
127
145
|
this.#currentValidator = nextValidator
|
|
128
146
|
}
|
package/test/factory.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import Factory from './../exports/factory.js'
|
|
2
|
+
import { expect } from 'chai'
|
|
3
|
+
|
|
4
|
+
describe('Factory', () => {
|
|
5
|
+
let factory
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
global.msg = {
|
|
9
|
+
sender: '0xOwnerAddress',
|
|
10
|
+
contract: '0xContractAddress',
|
|
11
|
+
staticCall: async (currency, method, args) => {
|
|
12
|
+
console.log(currency, method, args)
|
|
13
|
+
if (method === 'balanceOf') {
|
|
14
|
+
return BigInt(100000)
|
|
15
|
+
} else if (method === '_isContractCreator') {
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
call: async (currency, method, args) => {
|
|
20
|
+
console.log(currency, method, args)
|
|
21
|
+
|
|
22
|
+
if (method === 'balanceOf') {
|
|
23
|
+
return BigInt(100000)
|
|
24
|
+
} else if (method === '_isContractCreator') {
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
factory = new Factory('0xTokenAddress', BigInt(1000))
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should throw an error if balance is too low', async () => {
|
|
33
|
+
factory._canPay = () => false
|
|
34
|
+
try {
|
|
35
|
+
await factory.registerContract('0xContractAddress')
|
|
36
|
+
} catch (error) {
|
|
37
|
+
expect(error.message).to.equal("can't register, balance to low")
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should throw an error if address is not a contract creator', async () => {
|
|
42
|
+
factory._canPay = () => true
|
|
43
|
+
factory.isCreator = async () => false
|
|
44
|
+
try {
|
|
45
|
+
await factory.registerContract('0xContractAddress')
|
|
46
|
+
} catch (error) {
|
|
47
|
+
expect(error.message).to.equal("You don't own that contract")
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('should throw an error if contract is already registered', async () => {
|
|
52
|
+
await factory.registerContract('0xContractAddress')
|
|
53
|
+
try {
|
|
54
|
+
await factory.registerContract('0xContractAddress')
|
|
55
|
+
} catch (error) {
|
|
56
|
+
expect(error.message).to.equal('already registered')
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should successfully register a contract', async () => {
|
|
61
|
+
await factory.registerContract('0xContractAddress')
|
|
62
|
+
|
|
63
|
+
expect(factory.totalContracts).to.equal(BigInt(1))
|
|
64
|
+
expect(factory.contracts).to.include('0xContractAddress')
|
|
65
|
+
})
|
|
66
|
+
})
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { expect, use } from 'chai'
|
|
2
|
+
import chaiAsPromised from 'chai-as-promised'
|
|
3
|
+
import Leofcoin from './../exports/native-token.js'
|
|
4
|
+
import Token from '@leofcoin/standards/token.js'
|
|
5
|
+
|
|
6
|
+
use(chaiAsPromised)
|
|
7
|
+
|
|
8
|
+
describe('Leofcoin', () => {
|
|
9
|
+
let state
|
|
10
|
+
let token
|
|
11
|
+
const receiverAddress = '0xReceiverAddress'
|
|
12
|
+
const otherReceiverAddress = '0xOtherReceiverAddress'
|
|
13
|
+
const ownerAddress = '0xOwnerAddress'
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
global.msg = {
|
|
17
|
+
sender: ownerAddress,
|
|
18
|
+
contract: '0xContractAddress',
|
|
19
|
+
staticCall: async (currency, method, args) => {
|
|
20
|
+
// Mock implementation of msg.staticCall
|
|
21
|
+
},
|
|
22
|
+
call: async (currency, method, args) => {
|
|
23
|
+
// Mock implementation of msg.call
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
token = new Leofcoin()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should create an instance of Leofcoin', () => {
|
|
31
|
+
expect(token).to.be.instanceOf(Leofcoin)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should have correct properties', () => {
|
|
35
|
+
expect(token.name).to.equal('Leofcoin')
|
|
36
|
+
expect(token.symbol).to.equal('LFC')
|
|
37
|
+
expect(token.decimals).to.equal(18)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('should grant MINT role to owner', async () => {
|
|
41
|
+
await token.grantRole(ownerAddress, 'MINT')
|
|
42
|
+
expect(await token.hasRole(ownerAddress, 'MINT')).to.equal(true)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should be able to mint', async () => {
|
|
46
|
+
await token.grantRole(ownerAddress, 'MINT')
|
|
47
|
+
await token.mint(ownerAddress, 100000n)
|
|
48
|
+
expect(token.balanceOf(ownerAddress)).to.equal(100000n)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('should be able to transfer', async () => {
|
|
52
|
+
await token.grantRole(ownerAddress, 'MINT')
|
|
53
|
+
await token.mint(receiverAddress, 100000n)
|
|
54
|
+
msg.sender = receiverAddress
|
|
55
|
+
await token.transfer(receiverAddress, otherReceiverAddress, 10000n)
|
|
56
|
+
expect(token.balanceOf(receiverAddress)).to.equal(90000n)
|
|
57
|
+
expect(token.balanceOf(otherReceiverAddress)).to.equal(10000n)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should be able to burn', async () => {
|
|
61
|
+
await token.grantRole(ownerAddress, 'BURN')
|
|
62
|
+
await token.grantRole(ownerAddress, 'MINT')
|
|
63
|
+
await token.mint(ownerAddress, 100000n)
|
|
64
|
+
await token.burn(ownerAddress, 10000n)
|
|
65
|
+
expect(token.balanceOf(ownerAddress)).to.equal(90000n)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('should not be able to burn more than balance', async () => {
|
|
69
|
+
await token.grantRole(ownerAddress, 'MINT')
|
|
70
|
+
await token.mint(ownerAddress, 100000n)
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
await token.burn(ownerAddress, 100001n)
|
|
74
|
+
} catch (error) {
|
|
75
|
+
expect(error.message).to.equal('amount exceeds balance')
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('should not be able to mint if not MINT role', async () => {
|
|
80
|
+
try {
|
|
81
|
+
await token.mint(ownerAddress, 100000n)
|
|
82
|
+
} catch (error) {
|
|
83
|
+
expect(error.message).to.equal('mint role required')
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('should not be able to transfer more than balance', async () => {
|
|
88
|
+
await token.grantRole(ownerAddress, 'MINT')
|
|
89
|
+
await token.mint(receiverAddress, 100000n)
|
|
90
|
+
try {
|
|
91
|
+
await token.transfer(receiverAddress, otherReceiverAddress, 100001n)
|
|
92
|
+
} catch (error) {
|
|
93
|
+
expect(error.message).to.equal('amount exceeds balance')
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
})
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { expect, use } from 'chai'
|
|
2
|
+
import chaiAsPromised from 'chai-as-promised'
|
|
3
|
+
import { describe, it, beforeEach } from 'mocha'
|
|
4
|
+
import Validators from '../exports/validators.js'
|
|
5
|
+
|
|
6
|
+
use(chaiAsPromised)
|
|
7
|
+
|
|
8
|
+
describe('Validators', () => {
|
|
9
|
+
let validators
|
|
10
|
+
let validatorState
|
|
11
|
+
const tokenAddress = '0xTokenAddress'
|
|
12
|
+
const ownerAddress = '0xOwnerAddress'
|
|
13
|
+
const validatorAddress = '0xValidatorAddress'
|
|
14
|
+
const anotherValidatorAddress = '0xAnotherValidatorAddress'
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
global.state = {
|
|
18
|
+
peers: [
|
|
19
|
+
[ownerAddress, { bw: { up: 100, down: 100 } }],
|
|
20
|
+
[validatorAddress, { bw: { up: 100, down: 100 } }],
|
|
21
|
+
[anotherValidatorAddress, { bw: { up: 200, down: 200 } }]
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
global.msg = {
|
|
25
|
+
sender: ownerAddress,
|
|
26
|
+
contract: '0xContractAddress',
|
|
27
|
+
staticCall: async (currency, method, args) => {
|
|
28
|
+
if (method === 'balanceOf') {
|
|
29
|
+
if (args[0] === validatorAddress) return BigInt(100000)
|
|
30
|
+
if (args[0] === anotherValidatorAddress) return BigInt(100000)
|
|
31
|
+
}
|
|
32
|
+
return BigInt(0)
|
|
33
|
+
},
|
|
34
|
+
call: async (currency, method, args) => {
|
|
35
|
+
// Mock implementation of msg.call
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
validators = new Validators(tokenAddress, validatorState)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('should initialize with default values', () => {
|
|
42
|
+
expect(validators.name).to.equal('LeofcoinValidators')
|
|
43
|
+
expect(validators.currency).to.equal(tokenAddress)
|
|
44
|
+
expect(validators.validators).to.deep.equal([ownerAddress])
|
|
45
|
+
expect(validators.totalValidators).to.equal(1)
|
|
46
|
+
expect(validators.minimumBalance.toString()).to.equal(BigInt(50000).toString())
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('should change currency if sender is owner', () => {
|
|
50
|
+
validators.changeCurrency('0xNewCurrencyAddress')
|
|
51
|
+
expect(validators.currency).to.equal('0xNewCurrencyAddress')
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should throw error if non-owner tries to change currency', () => {
|
|
55
|
+
global.msg.sender = validatorAddress
|
|
56
|
+
expect(() => validators.changeCurrency('0xNewCurrencyAddress')).to.throw('not an owner')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should add a validator if conditions are met', async () => {
|
|
60
|
+
await validators.addValidator(validatorAddress)
|
|
61
|
+
expect(validators.validators).to.include(validatorAddress)
|
|
62
|
+
expect(validators.totalValidators).to.equal(2)
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('should throw error if adding an existing validator', async () => {
|
|
66
|
+
await validators.addValidator(validatorAddress)
|
|
67
|
+
await expect(validators.addValidator(validatorAddress)).to.be.rejectedWith(
|
|
68
|
+
'validator already exists'
|
|
69
|
+
)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('should throw error if validator balance is too low', async () => {
|
|
73
|
+
global.msg.staticCall = async (currency, method, args) => BigInt(1000)
|
|
74
|
+
await expect(validators.addValidator(anotherValidatorAddress)).to.be.rejectedWith(
|
|
75
|
+
'balance to low! got: 1000 need: 50000'
|
|
76
|
+
)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('should remove a validator if conditions are met', async () => {
|
|
80
|
+
await validators.addValidator(validatorAddress)
|
|
81
|
+
await validators.removeValidator(validatorAddress)
|
|
82
|
+
expect(validators.validators).to.not.include(validatorAddress)
|
|
83
|
+
expect(validators.totalValidators).to.equal(1)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('should throw error if removing a non-existing validator', async () => {
|
|
87
|
+
await expect(validators.removeValidator(validatorAddress)).to.be.rejectedWith(
|
|
88
|
+
'validator not found'
|
|
89
|
+
)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('should shuffle validator correctly', async () => {
|
|
93
|
+
validators.shuffleValidator()
|
|
94
|
+
expect(validators.currentValidator).to.include(ownerAddress)
|
|
95
|
+
await validators.removeValidator(ownerAddress)
|
|
96
|
+
|
|
97
|
+
global.msg.sender = validatorAddress
|
|
98
|
+
await validators.addValidator(validatorAddress)
|
|
99
|
+
|
|
100
|
+
validators.shuffleValidator()
|
|
101
|
+
expect(validators.currentValidator).to.include(validatorAddress)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('should return the current validator', () => {
|
|
105
|
+
expect(validators.currentValidator).to.equal(ownerAddress)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('should return state correctly', async () => {
|
|
109
|
+
msg.sender = validatorAddress
|
|
110
|
+
await validators.addValidator(validatorAddress)
|
|
111
|
+
validatorState = validators.state
|
|
112
|
+
expect(validatorState.validators).to.deep.equal([ownerAddress, validatorAddress])
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('should restore from state correctly', () => {
|
|
116
|
+
const newValidators = new Validators(tokenAddress, validatorState)
|
|
117
|
+
expect(newValidators.validators).to.deep.equal([ownerAddress, validatorAddress])
|
|
118
|
+
expect(newValidators.totalValidators).to.equal(2)
|
|
119
|
+
})
|
|
120
|
+
})
|
package/tsconfig.json
CHANGED
package/.changeset/README.md
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
# Changesets
|
|
2
|
-
|
|
3
|
-
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
|
4
|
-
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
|
5
|
-
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
|
6
|
-
|
|
7
|
-
We have a quick list of common questions to get you started engaging with this project in
|
|
8
|
-
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
package/.changeset/config.json
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
|
|
3
|
-
"changelog": "@changesets/cli/changelog",
|
|
4
|
-
"commit": true,
|
|
5
|
-
"fixed": [],
|
|
6
|
-
"linked": [],
|
|
7
|
-
"access": "public",
|
|
8
|
-
"baseBranch": "main",
|
|
9
|
-
"updateInternalDependencies": "patch",
|
|
10
|
-
"ignore": []
|
|
11
|
-
}
|
package/src/types.ts
DELETED