Created
May 8, 2018 09:09
-
-
Save dicarlo2/0243af7269a690a556b929294ed25e28 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
Address, | |
Event, | |
Fixed, | |
SmartContract, | |
notify, | |
verifySender, | |
} from '@neo-one/smart-contract'; | |
class Transfer extends Event { | |
constructor(from: Address, to: Address, amount: Fixed<8>) { | |
super(from, to, amount); | |
} | |
} | |
class Approve extends Event { | |
constructor(owner: Address, spender: Address, amount: Fixed<8>) { | |
super(owner, spender, amount); | |
} | |
} | |
export class Token extends SmartContract { | |
public readonly name: string = 'TestToken'; | |
public readonly decimals: 8 = 8; | |
public readonly symbol: string = 'TT'; | |
private readonly owner: Address; | |
private supply: Fixed<8> = 0; | |
private readonly balances: Map<Address, Fixed<8>> = new Map(); | |
private readonly allowances: Map<Address, Map<Address, Fixed<8>>> = new Map(); | |
constructor(owner: Address) { | |
super(); | |
this.owner = owner; | |
} | |
public transfer( | |
from: Address, | |
to: Address, | |
amount: Fixed<8>, | |
): void { | |
verifySender(from); | |
this.doTransfer(from, to, amount); | |
} | |
public transferFrom( | |
from: Address, | |
to: Address, | |
amount: Fixed<8>, | |
): void { | |
const available = this.allowance(from, to); | |
if (available < amount) { | |
throw new Error('Insufficient funds approved'); | |
} | |
this.doTransfer(from, to, amount); | |
this.setAllowance(from, to, available - amount); | |
} | |
public approve( | |
owner: Address, | |
spender: Address, | |
amount: Fixed<8>, | |
): void { | |
verifySender(owner); | |
const fromValue = this.balanceOf(owner); | |
if (fromValue < amount) { | |
throw new Error('Insufficient funds'); | |
} | |
this.setAllowance(owner, spender, this.allowance(owner, spender) + amount); | |
notify(new Approve(owner, spender, amount)); | |
} | |
public balanceOf(addr: Address): Fixed<8> { | |
return this.balances.get(addr) || 0; | |
} | |
public allowance(owner: Address, spender: Address): Fixed<8> { | |
return (this.allowances.get(owner) || new Map()).get(spender) || 0; | |
} | |
public get totalSupply(): Fixed<8> { | |
return this.supply; | |
} | |
protected issue(addr: Address, amount: Fixed<8>): void { | |
this.balances.set(addr, this.balanceOf(addr) + amount); | |
this.supply += amount; | |
notify(new Transfer(this.address, addr, amount)); | |
} | |
private doTransfer( | |
from: Address, | |
to: Address, | |
amount: Fixed<8>, | |
): void { | |
if (amount <= 0) { | |
throw new Error('Invalid amount'); | |
} | |
const fromValue = this.balanceOf(from); | |
if (fromValue < amount) { | |
throw new Error('Insufficient funds'); | |
} | |
this.balances.set(from, fromValue - amount); | |
this.balances.set(to, this.balanceOf(to) + amount); | |
notify(new Transfer(from, to, amount)); | |
} | |
private setAllowance( | |
from: Address, | |
to: Address, | |
amount: Fixed<8>, | |
): void { | |
let allowances = this.allowances.get(from); | |
if (allowances == null) { | |
allowances = new Map(); | |
} | |
allowances.set(to, amount); | |
this.allowances.set(from, allowances); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment