mirror of
https://github.com/status-im/keycard-redeem.git
synced 2025-01-11 12:44:14 +00:00
initial import
This commit is contained in:
commit
55dbd113f9
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
.embark
|
||||
chains.json
|
||||
config/livenet/password
|
||||
config/production/password
|
||||
coverage
|
||||
dist
|
||||
embarkArtifacts
|
||||
node_modules
|
357
CHANGELOG.md
Normal file
357
CHANGELOG.md
Normal file
@ -0,0 +1,357 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.1.1](https://github.com/embarklabs/embark/compare/v5.1.1-nightly.4...v5.1.1) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.1-nightly.4](https://github.com/embarklabs/embark/compare/v5.1.1-nightly.3...v5.1.1-nightly.4) (2020-02-03)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.1-nightly.2](https://github.com/embarklabs/embark/compare/v5.1.1-nightly.1...v5.1.1-nightly.2) (2020-01-31)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.1-nightly.1](https://github.com/embarklabs/embark/compare/v5.1.1-nightly.0...v5.1.1-nightly.1) (2020-01-30)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.1-nightly.0](https://github.com/embarklabs/embark/compare/v5.1.0...v5.1.1-nightly.0) (2020-01-29)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.1.0](https://github.com/embarklabs/embark/compare/v5.1.0-nightly.6...v5.1.0) (2020-01-27)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.1.0-nightly.6](https://github.com/embarklabs/embark/compare/v5.1.0-nightly.5...v5.1.0-nightly.6) (2020-01-25)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.1.0-nightly.5](https://github.com/embarklabs/embark/compare/v5.1.0-nightly.4...v5.1.0-nightly.5) (2020-01-24)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.1.0-nightly.4](https://github.com/embarklabs/embark/compare/v5.1.0-nightly.3...v5.1.0-nightly.4) (2020-01-23)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.1.0-nightly.3](https://github.com/embarklabs/embark/compare/v5.1.0-nightly.2...v5.1.0-nightly.3) (2020-01-22)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.1.0-nightly.2](https://github.com/embarklabs/embark/compare/v5.1.0-nightly.1...v5.1.0-nightly.2) (2020-01-21)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.1.0-nightly.1](https://github.com/embarklabs/embark/compare/v5.1.0-nightly.0...v5.1.0-nightly.1) (2020-01-20)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.1.0-nightly.0](https://github.com/embarklabs/embark/compare/v5.0.0...v5.1.0-nightly.0) (2020-01-17)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0](https://github.com/embarklabs/embark/compare/v5.0.0-beta.0...v5.0.0) (2020-01-07)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-beta.0](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.10...v5.0.0-beta.0) (2020-01-03)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.10](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.9...v5.0.0-alpha.10) (2019-12-24)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.9](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.8...v5.0.0-alpha.9) (2019-12-20)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.8](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.7...v5.0.0-alpha.8) (2019-12-19)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.7](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.6...v5.0.0-alpha.7) (2019-12-18)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.6](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.5...v5.0.0-alpha.6) (2019-12-17)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.5](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.4...v5.0.0-alpha.5) (2019-12-16)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.4](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.3...v5.0.0-alpha.4) (2019-12-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **@embark/whisper:** Add Whisper client config ([bd4b110](https://github.com/embarklabs/embark/commit/bd4b110))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.3](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.2...v5.0.0-alpha.3) (2019-12-06)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.2](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.1...v5.0.0-alpha.2) (2019-12-05)
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **@embark/library-manager:** restrict versionable packages to only solc ([2543aca](https://github.com/embarklabs/embark/commit/2543aca))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **@embark/library-manager:** Remove support for specifying the versions of `web3` and `ipfs-api` in a
|
||||
project's `embark.json`.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.1](https://github.com/embarklabs/embark/compare/v5.0.0-alpha.0...v5.0.0-alpha.1) (2019-11-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **@embark/templates:** ensure boilerplate template comes with valid whisper port ([bad2207](https://github.com/embarklabs/embark/commit/bad2207)), closes [/github.com/embarklabs/embark/commit/e330b338ea2a45acb14eebd93af93bc2aba62516#diff-a61fbc84e4172487789d676437f26b5fR14](https://github.com//github.com/embarklabs/embark/commit/e330b338ea2a45acb14eebd93af93bc2aba62516/issues/diff-a61fbc84e4172487789d676437f26b5fR14)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.0](https://github.com/embarklabs/embark/compare/v4.1.1...v5.0.0-alpha.0) (2019-10-28)
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* initial steps toward 5.0.0-alpha.0 ([#1856](https://github.com/embarklabs/embark/issues/1856)) ([b736ebe](https://github.com/embarklabs/embark/commit/b736ebe))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* There are more than several breaking changes, including DApp configuration for
|
||||
accounts.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.1.1](https://github.com/embarklabs/embark/compare/v4.1.0...v4.1.1) (2019-08-28)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.1.0](https://github.com/embarklabs/embark/compare/v4.1.0-beta.6...v4.1.0) (2019-08-12)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.1.0-beta.6](https://github.com/embarklabs/embark/compare/v4.1.0-beta.5...v4.1.0-beta.6) (2019-08-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **@embark/pipeline:** add minimalContractSize to remove bytecode ([b0cccae](https://github.com/embarklabs/embark/commit/b0cccae))
|
||||
* **@embark/pipeline:** enable choosing which fields to filter out ([b5c81bd](https://github.com/embarklabs/embark/commit/b5c81bd))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.1.0-beta.5](https://github.com/embarklabs/embark/compare/v4.1.0-beta.4...v4.1.0-beta.5) (2019-07-10)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.1.0-beta.4](https://github.com/embarklabs/embark/compare/v4.1.0-beta.3...v4.1.0-beta.4) (2019-06-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **@embark/dapps:** old link updated to the latest documentation at website ([09d7428](https://github.com/embarklabs/embark/commit/09d7428))
|
||||
* **templates:** fix templates because tests don't like empty files ([908aa3b](https://github.com/embarklabs/embark/commit/908aa3b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.1.0-beta.3](https://github.com/embarklabs/embark/compare/v4.1.0-beta.2...v4.1.0-beta.3) (2019-06-07)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.1.0-beta.2](https://github.com/embarklabs/embark/compare/v4.1.0-beta.1...v4.1.0-beta.2) (2019-05-22)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.1.0-beta.1](https://github.com/embarklabs/embark/compare/v4.1.0-beta.0...v4.1.0-beta.1) (2019-05-15)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.1.0-beta.0](https://github.com/embarklabs/embark/compare/v4.0.0...v4.1.0-beta.0) (2019-04-17)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.0.2](https://github.com/embarklabs/embark/compare/v4.0.1...v4.0.2) (2019-04-11)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [4.0.1](https://github.com/embarklabs/embark/compare/v4.0.0...v4.0.1) (2019-03-26)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.0.0](https://github.com/embarklabs/embark/compare/v4.0.0-beta.2...v4.0.0) (2019-03-18)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.0.0-beta.2](https://github.com/embarklabs/embark/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2019-03-18)
|
||||
|
||||
**Note:** Version bump only for package embark-dapp-template-boilerplate
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [4.0.0-beta.1](https://github.com/embarklabs/embark/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2019-03-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add repository.directory field to package.json ([a9c5e1a](https://github.com/embarklabs/embark/commit/a9c5e1a))
|
||||
* **@embark/pipeline:** Add `enabled` property to pipeline config ([5ea4807](https://github.com/embarklabs/embark/commit/5ea4807))
|
||||
* normalize README and package.json bugs, homepage, description ([5418f16](https://github.com/embarklabs/embark/commit/5418f16))
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 iuri matias
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
0
app/css/.gitkeep
Normal file
0
app/css/.gitkeep
Normal file
0
app/images/.gitkeep
Normal file
0
app/images/.gitkeep
Normal file
11
app/index.html
Normal file
11
app/index.html
Normal file
@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Embark</title>
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
<script src="js/app.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h3>Welcome to Embark!</h3>
|
||||
<p>See the <a href="https://framework.embarklabs.io/docs/quick_start.html" target="_blank">Embark's documentation</a> to see what you can do with Embark!</p>
|
||||
</body>
|
||||
</html>
|
0
app/js/.gitkeep
Normal file
0
app/js/.gitkeep
Normal file
10
app/js/index.js
Normal file
10
app/js/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
import EmbarkJS from 'Embark/EmbarkJS';
|
||||
|
||||
// import your contracts
|
||||
// e.g if you have a contract named SimpleStorage:
|
||||
//import SimpleStorage from 'Embark/contracts/SimpleStorage';
|
||||
|
||||
|
||||
EmbarkJS.onReady((err) => {
|
||||
// You can execute contract calls after the connection
|
||||
});
|
78
config/blockchain.js
Normal file
78
config/blockchain.js
Normal file
@ -0,0 +1,78 @@
|
||||
// This file contains only the basic configuration you need to run Embark's node
|
||||
// For additional configurations, see: https://framework.embarklabs.io/docs/blockchain_configuration.html
|
||||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
enabled: true,
|
||||
client: "geth" // Can be geth or parity (default:geth)
|
||||
},
|
||||
|
||||
development: {
|
||||
clientConfig: {
|
||||
miningMode: 'dev' // Mode in which the node mines. Options: dev, auto, always, off
|
||||
}
|
||||
},
|
||||
|
||||
privatenet: {
|
||||
// Accounts to use as node accounts
|
||||
// The order here corresponds to the order of `web3.eth.getAccounts`, so the first one is the `defaultAccount`
|
||||
// For more account configurations, see: https://framework.embarklabs.io/docs/blockchain_accounts_configuration.html
|
||||
accounts: [
|
||||
{
|
||||
nodeAccounts: true, // Accounts use for the node
|
||||
numAddresses: "1", // Number of addresses/accounts (defaults to 1)
|
||||
password: "config/development/password" // Password file for the accounts
|
||||
}
|
||||
],
|
||||
clientConfig: {
|
||||
datadir: ".embark/privatenet/datadir", // Data directory for the databases and keystore
|
||||
miningMode: 'auto',
|
||||
genesisBlock: "config/privatenet/genesis.json" // Genesis block to initiate on first creation of a development node
|
||||
}
|
||||
},
|
||||
|
||||
privateparitynet: {
|
||||
client: "parity",
|
||||
genesisBlock: "config/privatenet/genesis-parity.json",
|
||||
datadir: ".embark/privatenet/datadir",
|
||||
miningMode: 'off'
|
||||
},
|
||||
|
||||
externalnode: {
|
||||
endpoint: "URL_OF_THE_NODE", // Endpoint of an node to connect to. Can be on localhost or on the internet
|
||||
accounts: [
|
||||
{
|
||||
mnemonic: "YOUR_MNEMONIC",
|
||||
hdpath: "m/44'/60'/0'/0/",
|
||||
numAddresses: "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
testnet: {
|
||||
networkType: "testnet", // Can be: testnet(ropsten), rinkeby, livenet or custom, in which case, it will use the specified networkId
|
||||
syncMode: "light",
|
||||
accounts: [
|
||||
{
|
||||
nodeAccounts: true,
|
||||
password: "config/testnet/password"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
livenet: {
|
||||
networkType: "livenet",
|
||||
syncMode: "light",
|
||||
accounts: [
|
||||
{
|
||||
nodeAccounts: true,
|
||||
password: "config/livenet/password"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name" or "embark blockchain custom_name"
|
||||
//custom_name: {
|
||||
//}
|
||||
};
|
47
config/communication.js
Normal file
47
config/communication.js
Normal file
@ -0,0 +1,47 @@
|
||||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
enabled: true,
|
||||
provider: "whisper", // Communication provider. Currently, Embark only supports whisper
|
||||
available_providers: ["whisper"], // Array of available providers
|
||||
client: "geth"
|
||||
},
|
||||
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run`
|
||||
development: {
|
||||
connection: {
|
||||
host: "localhost", // Host of the provider node
|
||||
port: 8547, // Port of the provider node
|
||||
type: "ws" // Type of connection (ws or rpc)
|
||||
}
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run privatenet"
|
||||
privatenet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run testnet"
|
||||
testnet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run livenet"
|
||||
livenet: {
|
||||
},
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name"
|
||||
//custom_name: {
|
||||
//}
|
||||
// Use this section when you need a specific symmetric or private keys in whisper
|
||||
/*
|
||||
,keys: {
|
||||
symmetricKey: "your_symmetric_key",// Symmetric key for message decryption
|
||||
privateKey: "your_private_key" // Private Key to be used as a signing key and for message decryption
|
||||
}
|
||||
*/
|
||||
//}
|
||||
};
|
51
config/contracts.js
Normal file
51
config/contracts.js
Normal file
@ -0,0 +1,51 @@
|
||||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
// order of connections the dapp should connect to
|
||||
dappConnection: [
|
||||
"$EMBARK",
|
||||
"$WEB3", // uses pre existing web3 object if available (e.g in Mist)
|
||||
"ws://localhost:8546",
|
||||
"http://localhost:8545"
|
||||
],
|
||||
|
||||
// Automatically call `ethereum.enable` if true.
|
||||
// If false, the following code must run before sending any transaction: `await EmbarkJS.enableEthereum();`
|
||||
// Default value is true.
|
||||
// dappAutoEnable: true,
|
||||
|
||||
gas: "auto",
|
||||
|
||||
// Strategy for the deployment of the contracts:
|
||||
// - implicit will try to deploy all the contracts located inside the contracts directory
|
||||
// or the directory configured for the location of the contracts. This is default one
|
||||
// when not specified
|
||||
// - explicit will only attempt to deploy the contracts that are explicitly specified inside the
|
||||
// contracts section.
|
||||
// strategy: 'implicit',
|
||||
|
||||
// minimalContractSize, when set to true, tells Embark to generate contract files without the heavy bytecodes
|
||||
// Using filteredFields lets you customize which field you want to filter out of the contract file (requires minimalContractSize: true)
|
||||
// minimalContractSize: false,
|
||||
// filteredFields: [],
|
||||
|
||||
deploy: {
|
||||
// example:
|
||||
//SimpleStorage: {
|
||||
// args: [ 100 ]
|
||||
//}
|
||||
}
|
||||
},
|
||||
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run`
|
||||
development: {},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run privatenet"
|
||||
privatenet: {},
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name" or "embark blockchain custom_name"
|
||||
// custom_name: {}
|
||||
};
|
1
config/development/password
Normal file
1
config/development/password
Normal file
@ -0,0 +1 @@
|
||||
dev_password
|
39
config/namesystem.js
Normal file
39
config/namesystem.js
Normal file
@ -0,0 +1,39 @@
|
||||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
enabled: true,
|
||||
available_providers: ["ens"],
|
||||
provider: "ens"
|
||||
},
|
||||
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run`
|
||||
development: {
|
||||
register: {
|
||||
rootDomain: "embark.eth",
|
||||
subdomains: {
|
||||
'status': '0x1a2f3b98e434c02363f3dac3174af93c1d690914'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run privatenet"
|
||||
privatenet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run testnet"
|
||||
testnet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run livenet"
|
||||
livenet: {
|
||||
},
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name" or "embark blockchain custom_name"
|
||||
//custom_name: {
|
||||
//}
|
||||
};
|
29
config/pipeline.js
Normal file
29
config/pipeline.js
Normal file
@ -0,0 +1,29 @@
|
||||
// Embark has support for Flow enabled by default in its built-in webpack
|
||||
// config: type annotations will automatically be stripped out of DApp sources
|
||||
// without any additional configuration. Note that type checking is not
|
||||
// performed during builds.
|
||||
|
||||
// To enable Flow type checking refer to the preconfigured template:
|
||||
// https://github.com/embarklabs/embark-flow-template
|
||||
// A new DApp can be created from that template with:
|
||||
// embark new --template flow
|
||||
// NOTE: the `--template` option is DEPRECATED in v5.
|
||||
|
||||
module.exports = {
|
||||
typescript: false,
|
||||
// Setting `typescript: true` in this config will disable Flow support in
|
||||
// Embark's default webpack config and enable TypeScript support: .ts and
|
||||
// .tsx sources will automatically be transpiled into JavaScript without any
|
||||
// additional configuration. Note that type checking is not performed during
|
||||
// builds.
|
||||
|
||||
// To enable TypeScript type checking refer to the preconfigured template:
|
||||
// https://github.com/embarklabs/embark-typescript-template
|
||||
// A new DApp can be created from that template with:
|
||||
// embark new --template typescript
|
||||
// NOTE: the `--template` option is DEPRECATED in v5.
|
||||
enabled: true
|
||||
// Setting `enabled: false` in this config will disable Embark's built-in Webpack
|
||||
// pipeline. The developer will need to use a different frontend build tool, such as
|
||||
// `create-react-app` or Angular CLI to build their dapp
|
||||
};
|
147
config/privatenet/genesis-parity.json
Normal file
147
config/privatenet/genesis-parity.json
Normal file
File diff suppressed because one or more lines are too long
20
config/privatenet/genesis.json
Normal file
20
config/privatenet/genesis.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"config": {
|
||||
"homesteadBlock": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"daoForkSupport": true
|
||||
},
|
||||
"nonce": "0x0000000000000042",
|
||||
"difficulty": "0x0",
|
||||
"alloc": {
|
||||
"0x3333333333333333333333333333333333333333": {"balance": "15000000000000000000"}
|
||||
},
|
||||
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase": "0x3333333333333333333333333333333333333333",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x7a1200"
|
||||
}
|
1
config/privatenet/password
Normal file
1
config/privatenet/password
Normal file
@ -0,0 +1 @@
|
||||
dev_password
|
58
config/storage.js
Normal file
58
config/storage.js
Normal file
@ -0,0 +1,58 @@
|
||||
module.exports = {
|
||||
// default applies to all environments
|
||||
default: {
|
||||
enabled: true,
|
||||
ipfs_bin: "ipfs",
|
||||
available_providers: ["ipfs"],
|
||||
upload: {
|
||||
provider: "ipfs",
|
||||
host: "localhost",
|
||||
port: 5001
|
||||
},
|
||||
dappConnection: [
|
||||
{
|
||||
provider: "ipfs",
|
||||
host: "localhost",
|
||||
port: 5001,
|
||||
getUrl: "http://localhost:8080/ipfs/"
|
||||
}
|
||||
]
|
||||
// Configuration to start Swarm in the same terminal as `embark run`
|
||||
/*,account: {
|
||||
address: "YOUR_ACCOUNT_ADDRESS", // Address of account accessing Swarm
|
||||
password: "PATH/TO/PASSWORD/FILE" // File containing the password of the account
|
||||
},
|
||||
swarmPath: "PATH/TO/SWARM/EXECUTABLE" // Path to swarm executable (default: swarm)*/
|
||||
},
|
||||
|
||||
// default environment, merges with the settings in default
|
||||
// assumed to be the intended environment by `embark run`
|
||||
development: {
|
||||
upload: {
|
||||
provider: "ipfs",
|
||||
host: "localhost",
|
||||
port: 5001,
|
||||
getUrl: "http://localhost:8080/ipfs/"
|
||||
}
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run privatenet"
|
||||
privatenet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run testnet"
|
||||
testnet: {
|
||||
},
|
||||
|
||||
// merges with the settings in default
|
||||
// used with "embark run livenet"
|
||||
livenet: {
|
||||
},
|
||||
|
||||
// you can name an environment with specific settings and then specify with
|
||||
// "embark run custom_name"
|
||||
//custom_name: {
|
||||
//}
|
||||
};
|
1
config/testnet/password
Normal file
1
config/testnet/password
Normal file
@ -0,0 +1 @@
|
||||
test_password
|
6
config/webserver.js
Normal file
6
config/webserver.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
enabled: true,
|
||||
host: "localhost",
|
||||
openBrowser: true,
|
||||
port: 8000
|
||||
};
|
0
contracts/.gitkeep
Normal file
0
contracts/.gitkeep
Normal file
15
contracts/ERC20Token.sol
Normal file
15
contracts/ERC20Token.sol
Normal file
@ -0,0 +1,15 @@
|
||||
pragma solidity ^0.6.1;
|
||||
|
||||
// https://github.com/ethereum/EIPs/issues/20
|
||||
|
||||
interface ERC20Token {
|
||||
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||
|
||||
function transfer(address _to, uint256 _value) external returns (bool success);
|
||||
function approve(address _spender, uint256 _value) external returns (bool success);
|
||||
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
|
||||
function balanceOf(address _owner) external view returns (uint256 balance);
|
||||
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
|
||||
function totalSupply() external view returns (uint256 supply);
|
||||
}
|
146
contracts/GiftsBatch.sol
Normal file
146
contracts/GiftsBatch.sol
Normal file
@ -0,0 +1,146 @@
|
||||
pragma solidity ^0.6.1;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./ERC20Token.sol";
|
||||
|
||||
contract GiftsBatch {
|
||||
|
||||
address payable public owner;
|
||||
|
||||
ERC20Token public tokenContract;
|
||||
|
||||
uint256 public expirationTime;
|
||||
|
||||
struct Gift {
|
||||
address keycard;
|
||||
uint256 amount;
|
||||
bytes32 code;
|
||||
}
|
||||
|
||||
mapping(address => Gift) public gifts;
|
||||
|
||||
uint256 public totalSupply;
|
||||
uint256 public availableSupply;
|
||||
|
||||
struct Redeem {
|
||||
address keycard;
|
||||
address receiver;
|
||||
bytes32 code;
|
||||
}
|
||||
|
||||
bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
|
||||
bytes32 constant REDEEM_TYPEHASH = keccak256("Redeem(address keycard,address receiver,bytes32 code)");
|
||||
bytes32 DOMAIN_SEPARATOR;
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == owner, "owner required");
|
||||
_;
|
||||
}
|
||||
|
||||
constructor(address _tokenAddress, uint256 _expirationTime) public {
|
||||
tokenContract = ERC20Token(_tokenAddress);
|
||||
expirationTime = _expirationTime;
|
||||
owner = msg.sender;
|
||||
DOMAIN_SEPARATOR = keccak256(abi.encode(
|
||||
EIP712DOMAIN_TYPEHASH,
|
||||
keccak256("KeycardGift"),
|
||||
keccak256("1"),
|
||||
getChainID(),
|
||||
address(this)
|
||||
));
|
||||
}
|
||||
|
||||
function getChainID() internal pure returns (uint256) {
|
||||
uint256 id;
|
||||
assembly {
|
||||
id := chainid()
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
function addSupply(uint256 amount) external onlyOwner {
|
||||
bool success = tokenContract.transferFrom(msg.sender, address(this), amount);
|
||||
assert(success);
|
||||
totalSupply += amount;
|
||||
availableSupply += amount;
|
||||
}
|
||||
|
||||
function createGift(address keycard, uint256 amount, bytes32 code) external onlyOwner {
|
||||
require(amount > 0, "invalid amount");
|
||||
require(availableSupply >= amount, "low supply");
|
||||
|
||||
Gift storage gift = gifts[keycard];
|
||||
require(gift.amount == 0, "keycard already used");
|
||||
|
||||
gift.keycard = keycard;
|
||||
gift.amount = amount;
|
||||
gift.code = code;
|
||||
|
||||
availableSupply -= amount;
|
||||
}
|
||||
|
||||
// function redeem(address keycard, address receiver, bytes32 code, bytes calldata sig) external {
|
||||
function redeem(Redeem calldata _redeem, bytes calldata sig) external {
|
||||
require(block.timestamp < expirationTime, "expired gift");
|
||||
|
||||
bool signedByKeycard = verify(_redeem, sig);
|
||||
require(signedByKeycard, "not signed by keycard");
|
||||
|
||||
Gift memory gift = gifts[_redeem.keycard];
|
||||
require(gift.amount > 0, "not found");
|
||||
|
||||
bytes32 codeHash = keccak256(abi.encodePacked(_redeem.code));
|
||||
require(codeHash == gift.code, "invalid code");
|
||||
|
||||
|
||||
totalSupply -= gift.amount;
|
||||
tokenContract.transfer(_redeem.receiver, gift.amount);
|
||||
}
|
||||
|
||||
function kill() external onlyOwner {
|
||||
require(block.timestamp >= expirationTime, "not expired yet");
|
||||
|
||||
bool success = tokenContract.transfer(owner, totalSupply);
|
||||
assert(success);
|
||||
|
||||
selfdestruct(owner);
|
||||
}
|
||||
|
||||
function hashRedeem(Redeem memory _redeem) internal pure returns (bytes32) {
|
||||
return keccak256(abi.encode(
|
||||
REDEEM_TYPEHASH,
|
||||
_redeem.keycard,
|
||||
_redeem.receiver,
|
||||
_redeem.code
|
||||
));
|
||||
}
|
||||
|
||||
function verify(Redeem memory _redeem, bytes memory sig) internal view returns(bool) {
|
||||
require(sig.length == 65, "bad signature length");
|
||||
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
uint8 v;
|
||||
|
||||
assembly {
|
||||
r := mload(add(sig, 32))
|
||||
s := mload(add(sig, 64))
|
||||
v := byte(0, mload(add(sig, 96)))
|
||||
}
|
||||
|
||||
if (v < 27) {
|
||||
v += 27;
|
||||
}
|
||||
|
||||
require(v == 27 || v == 28, "signature version doesn't match");
|
||||
|
||||
bytes32 digest = keccak256(abi.encodePacked(
|
||||
"\x19\x01",
|
||||
DOMAIN_SEPARATOR,
|
||||
hashRedeem(_redeem)
|
||||
));
|
||||
|
||||
return ecrecover(digest, v, r, s) == _redeem.keycard;
|
||||
}
|
||||
}
|
110
contracts/StandardToken.sol
Normal file
110
contracts/StandardToken.sol
Normal file
@ -0,0 +1,110 @@
|
||||
pragma solidity ^0.6.1;
|
||||
|
||||
import "./ERC20Token.sol";
|
||||
|
||||
contract StandardToken is ERC20Token {
|
||||
|
||||
uint256 private supply;
|
||||
mapping (address => uint256) balances;
|
||||
mapping (address => mapping (address => uint256)) allowed;
|
||||
|
||||
constructor() internal { }
|
||||
|
||||
function transfer(
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
external
|
||||
override(ERC20Token)
|
||||
returns (bool success)
|
||||
{
|
||||
return transfer(msg.sender, _to, _value);
|
||||
}
|
||||
|
||||
function approve(address _spender, uint256 _value)
|
||||
external
|
||||
override(ERC20Token)
|
||||
returns (bool success)
|
||||
{
|
||||
allowed[msg.sender][_spender] = _value;
|
||||
emit Approval(msg.sender, _spender, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function transferFrom(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
external
|
||||
override(ERC20Token)
|
||||
returns (bool success)
|
||||
{
|
||||
if (balances[_from] >= _value &&
|
||||
allowed[_from][msg.sender] >= _value &&
|
||||
_value > 0) {
|
||||
allowed[_from][msg.sender] -= _value;
|
||||
return transfer(_from, _to, _value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function allowance(address _owner, address _spender)
|
||||
external
|
||||
view
|
||||
override(ERC20Token)
|
||||
returns (uint256 remaining)
|
||||
{
|
||||
return allowed[_owner][_spender];
|
||||
}
|
||||
|
||||
function balanceOf(address _owner)
|
||||
external
|
||||
view
|
||||
override(ERC20Token)
|
||||
returns (uint256 balance)
|
||||
{
|
||||
return balances[_owner];
|
||||
}
|
||||
|
||||
function totalSupply()
|
||||
external
|
||||
view
|
||||
override(ERC20Token)
|
||||
returns(uint256 currentTotalSupply)
|
||||
{
|
||||
return supply;
|
||||
}
|
||||
|
||||
function mint(
|
||||
address _to,
|
||||
uint256 _amount
|
||||
)
|
||||
internal
|
||||
{
|
||||
balances[_to] += _amount;
|
||||
supply += _amount;
|
||||
emit Transfer(address(0x0), _to, _amount);
|
||||
}
|
||||
|
||||
function transfer(
|
||||
address _from,
|
||||
address _to,
|
||||
uint256 _value
|
||||
)
|
||||
internal
|
||||
returns (bool success)
|
||||
{
|
||||
if (balances[_from] >= _value && _value > 0) {
|
||||
balances[_from] -= _value;
|
||||
balances[_to] += _value;
|
||||
emit Transfer(_from, _to, _value);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
19
contracts/TestToken.sol
Normal file
19
contracts/TestToken.sol
Normal file
@ -0,0 +1,19 @@
|
||||
pragma solidity ^0.6.1;
|
||||
|
||||
import "./StandardToken.sol";
|
||||
|
||||
/**
|
||||
* @notice ERC20Token for test scripts, can be minted by anyone.
|
||||
*/
|
||||
contract TestToken is StandardToken {
|
||||
|
||||
constructor() public { }
|
||||
|
||||
/**
|
||||
* @notice any caller can mint any `_amount`
|
||||
* @param _amount how much to be minted
|
||||
*/
|
||||
function mint(uint256 _amount) public {
|
||||
mint(msg.sender, _amount);
|
||||
}
|
||||
}
|
23
embark.json
Normal file
23
embark.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"contracts": ["contracts/**"],
|
||||
"app": {
|
||||
"css/app.css": ["app/css/**"],
|
||||
"js/app.js": ["app/js/index.js"],
|
||||
"images/": ["app/images/**"],
|
||||
"index.html": "app/index.html"
|
||||
},
|
||||
"buildDir": "dist/",
|
||||
"config": "config/",
|
||||
"versions": {
|
||||
"solc": "0.6.1"
|
||||
},
|
||||
"plugins": {
|
||||
},
|
||||
"options": {
|
||||
"solc": {
|
||||
"optimize": true,
|
||||
"optimize-runs": 200
|
||||
}
|
||||
},
|
||||
"generationDir": "embarkArtifacts"
|
||||
}
|
4944
package-lock.json
generated
Normal file
4944
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
package.json
Normal file
19
package.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "gift-keycard",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"test": "embark test"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"embarkjs": "^5.1.1",
|
||||
"embarkjs-ens": "^5.1.1",
|
||||
"embarkjs-ipfs": "^5.1.1",
|
||||
"embarkjs-swarm": "^5.1.1",
|
||||
"embarkjs-web3": "^5.1.1",
|
||||
"embarkjs-whisper": "^5.1.1"
|
||||
}
|
||||
}
|
307
test/contract_spec.js
Normal file
307
test/contract_spec.js
Normal file
@ -0,0 +1,307 @@
|
||||
const TestToken = require('Embark/contracts/TestToken');
|
||||
const GiftsBatch = require('Embark/contracts/GiftsBatch');
|
||||
|
||||
let shop,
|
||||
user;
|
||||
|
||||
// For documentation please see https://framework.embarklabs.io/docs/contracts_testing.html
|
||||
config({
|
||||
contracts: {
|
||||
deploy: {
|
||||
"TestToken": {
|
||||
args: [],
|
||||
}
|
||||
}
|
||||
}
|
||||
}, (_err, _accounts) => {
|
||||
shop = _accounts[0];
|
||||
keycard_1 = _accounts[1];
|
||||
keycard_2 = _accounts[2];
|
||||
user = _accounts[3];
|
||||
});
|
||||
|
||||
const TOTAL_SUPPLY = 10000;
|
||||
const GIFT_AMOUNT = 10;
|
||||
const REDEEM_CODE = web3.utils.sha3("hello world");
|
||||
const NOW = Math.round(new Date().getTime() / 1000);
|
||||
const EXPIRATION_TIME = NOW + 60 * 60 * 24; // in 24 hours
|
||||
|
||||
let sendMethod;
|
||||
|
||||
async function signRedeem(contractAddress, signer, message) {
|
||||
const result = await web3.eth.net.getId();
|
||||
const chainId = parseInt(result);
|
||||
|
||||
let domain = [
|
||||
{ name: "name", type: "string" },
|
||||
{ name: "version", type: "string" },
|
||||
{ name: "chainId", type: "uint256" },
|
||||
{ name: "verifyingContract", type: "address" }
|
||||
];
|
||||
|
||||
let redeem = [
|
||||
{ name: "keycard", type: "address" },
|
||||
{ name: "receiver", type: "address" },
|
||||
{ name: "code", type: "bytes32" },
|
||||
];
|
||||
|
||||
let domainData = {
|
||||
name: "KeycardGift",
|
||||
version: "1",
|
||||
chainId: chainId,
|
||||
verifyingContract: contractAddress
|
||||
};
|
||||
|
||||
let data = {
|
||||
types: {
|
||||
EIP712Domain: domain,
|
||||
Redeem: redeem,
|
||||
},
|
||||
primaryType: "Redeem",
|
||||
domain: domainData,
|
||||
message: message
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
sendMethod({
|
||||
jsonrpc: '2.0',
|
||||
id: Date.now().toString().substring(9),
|
||||
method: "eth_signTypedData",
|
||||
params: [signer, data],
|
||||
from: keycard_2
|
||||
}, (error, res) => {
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
resolve(res.result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function mineAt(timestamp) {
|
||||
return new Promise((resolve, reject) => {
|
||||
sendMethod({
|
||||
jsonrpc: '2.0',
|
||||
method: "evm_mine",
|
||||
params: [timestamp],
|
||||
id: Date.now().toString().substring(9)
|
||||
}, (error, res) => {
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
resolve(res.result);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
contract("TestToken", function () {
|
||||
sendMethod = (web3.currentProvider.sendAsync) ? web3.currentProvider.sendAsync.bind(web3.currentProvider) : web3.currentProvider.send.bind(web3.currentProvider);
|
||||
|
||||
let giftsBatchInstance;
|
||||
|
||||
it("shop buys 100 tokens", async function () {
|
||||
let supply = await TestToken.methods.totalSupply().call();
|
||||
assert.equal(parseInt(supply), 0);
|
||||
|
||||
await TestToken.methods.mint(TOTAL_SUPPLY).send({
|
||||
from: shop,
|
||||
});
|
||||
|
||||
supply = await TestToken.methods.totalSupply().call();
|
||||
assert.equal(parseInt(supply), TOTAL_SUPPLY);
|
||||
|
||||
let shopBalance = await TestToken.methods.balanceOf(shop).call();
|
||||
assert.equal(parseInt(shopBalance), TOTAL_SUPPLY);
|
||||
});
|
||||
|
||||
it("deploy", async function() {
|
||||
const deploy = GiftsBatch.deploy({
|
||||
arguments: [TestToken.address, EXPIRATION_TIME],
|
||||
});
|
||||
giftsBatchInstance = await deploy.send({
|
||||
gas: 900000,
|
||||
});
|
||||
|
||||
const approve = TestToken.methods.approve(giftsBatchInstance._address, TOTAL_SUPPLY)
|
||||
const approveGas = await approve.estimateGas();
|
||||
await approve.send({
|
||||
from: shop,
|
||||
gas: approveGas,
|
||||
});
|
||||
|
||||
|
||||
const addSupply = giftsBatchInstance.methods.addSupply(TOTAL_SUPPLY)
|
||||
const addSupplyGas = await addSupply.estimateGas();
|
||||
await addSupply.send({
|
||||
from: shop,
|
||||
gas: addSupplyGas,
|
||||
});
|
||||
|
||||
let shopBalance = await TestToken.methods.balanceOf(shop).call();
|
||||
assert.equal(parseInt(shopBalance), 0);
|
||||
|
||||
let factoryBalance = await TestToken.methods.balanceOf(giftsBatchInstance._address).call();
|
||||
assert.equal(parseInt(factoryBalance), TOTAL_SUPPLY);
|
||||
|
||||
let totalSupply = await giftsBatchInstance.methods.totalSupply().call();
|
||||
assert.equal(parseInt(totalSupply), TOTAL_SUPPLY);
|
||||
|
||||
let availableSupply = await giftsBatchInstance.methods.availableSupply().call();
|
||||
assert.equal(parseInt(availableSupply), TOTAL_SUPPLY);
|
||||
});
|
||||
|
||||
async function testCreateGift(keycard, amount) {
|
||||
const redeemCodeHash = web3.utils.sha3(REDEEM_CODE);
|
||||
const createGift = giftsBatchInstance.methods.createGift(keycard, amount, redeemCodeHash);
|
||||
const createGiftGas = await createGift.estimateGas();
|
||||
await createGift.send({
|
||||
from: shop,
|
||||
gas: createGiftGas,
|
||||
});
|
||||
|
||||
let totalSupply = await giftsBatchInstance.methods.totalSupply().call();
|
||||
assert.equal(parseInt(totalSupply), TOTAL_SUPPLY);
|
||||
|
||||
let availableSupply = await giftsBatchInstance.methods.availableSupply().call();
|
||||
assert.equal(parseInt(availableSupply), TOTAL_SUPPLY - amount);
|
||||
}
|
||||
|
||||
it("createGift should fail amount is zero", async function() {
|
||||
try {
|
||||
await testCreateGift(keycard_1, 0);
|
||||
assert.fail("createGift should have failed");
|
||||
} catch(e) {
|
||||
assert.match(e.message, /invalid amount/);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it("createGift fails if amount > totalSupply", async function() {
|
||||
try {
|
||||
await testCreateGift(keycard_1, TOTAL_SUPPLY + 1);
|
||||
assert.fail("createGift should have failed");
|
||||
} catch(e) {
|
||||
assert.match(e.message, /low supply/);
|
||||
}
|
||||
});
|
||||
|
||||
it("createGift", async function() {
|
||||
await testCreateGift(keycard_1, GIFT_AMOUNT);
|
||||
});
|
||||
|
||||
it("createGift should fail if keycard has already been used", async function() {
|
||||
try {
|
||||
await testCreateGift(keycard_1, 1);
|
||||
assert.fail("createGift should have failed");
|
||||
} catch(e) {
|
||||
assert.match(e.message, /keycard already used/);
|
||||
}
|
||||
});
|
||||
|
||||
it("createGift amount > availableSupply", async function() {
|
||||
try {
|
||||
await testCreateGift(keycard_2, TOTAL_SUPPLY - GIFT_AMOUNT + 1);
|
||||
assert.fail("createGift should have failed");
|
||||
} catch(e) {
|
||||
assert.match(e.message, /low supply/);
|
||||
}
|
||||
});
|
||||
|
||||
async function testRedeem(redeemCode) {
|
||||
let totalSupply = await giftsBatchInstance.methods.totalSupply().call();
|
||||
assert.equal(parseInt(totalSupply), TOTAL_SUPPLY);
|
||||
|
||||
let factoryBalance = await TestToken.methods.balanceOf(giftsBatchInstance._address).call();
|
||||
assert.equal(parseInt(factoryBalance), TOTAL_SUPPLY);
|
||||
|
||||
let userBalance = await TestToken.methods.balanceOf(user).call();
|
||||
assert.equal(parseInt(userBalance), 0);
|
||||
|
||||
// const gift = await giftsBatchInstance.methods.gifts(keycard_1).call();
|
||||
// const giftBlockNumber = gift.blockNumber;
|
||||
// const message = web3.utils.sha3(user);
|
||||
// const sig = await web3.eth.sign(message, keycard_1);
|
||||
|
||||
const message = {
|
||||
keycard: keycard_1,
|
||||
receiver: user,
|
||||
code: redeemCode,
|
||||
};
|
||||
|
||||
const sig = await signRedeem(giftsBatchInstance._address, keycard_1, message);
|
||||
|
||||
const redeem = giftsBatchInstance.methods.redeem(message, sig);
|
||||
const redeemGas = await redeem.estimateGas();
|
||||
await redeem.send({
|
||||
from: user,
|
||||
gas: redeemGas,
|
||||
});
|
||||
|
||||
factoryBalance = await TestToken.methods.balanceOf(giftsBatchInstance._address).call();
|
||||
assert.equal(parseInt(factoryBalance), TOTAL_SUPPLY - GIFT_AMOUNT);
|
||||
|
||||
userBalance = await TestToken.methods.balanceOf(user).call();
|
||||
assert.equal(parseInt(userBalance), GIFT_AMOUNT);
|
||||
|
||||
totalSupply = await giftsBatchInstance.methods.totalSupply().call();
|
||||
assert.equal(parseInt(totalSupply), TOTAL_SUPPLY - GIFT_AMOUNT);
|
||||
}
|
||||
|
||||
// it("cannot redeem after expiration date", async function() {
|
||||
// await mineAt(EXPIRATION_TIME);
|
||||
// try {
|
||||
// await testRedeem(REDEEM_CODE);
|
||||
// assert.fail("redeem should have failed");
|
||||
// } catch(e) {
|
||||
// assert.match(e.message, /expired/);
|
||||
// }
|
||||
// });
|
||||
|
||||
// it("cannot redeem with invalid code", async function() {
|
||||
// await mineAt(NOW);
|
||||
// try {
|
||||
// await testRedeem(web3.utils.sha3("bad-code"));
|
||||
// assert.fail("redeem should have failed");
|
||||
// } catch(e) {
|
||||
// assert.match(e.message, /invalid code/);
|
||||
// }
|
||||
// });
|
||||
|
||||
it("can redeem before expiration date", async function() {
|
||||
await mineAt(NOW);
|
||||
await testRedeem(REDEEM_CODE);
|
||||
});
|
||||
|
||||
// async function testKill() {
|
||||
// let shopBalance = await TestToken.methods.balanceOf(shop).call();
|
||||
// assert.equal(parseInt(shopBalance), 0);
|
||||
|
||||
// let factoryBalance = await TestToken.methods.balanceOf(giftsBatchInstance._address).call();
|
||||
// assert.equal(parseInt(factoryBalance), TOTAL_SUPPLY - GIFT_AMOUNT);
|
||||
|
||||
// await giftsBatchInstance.methods.kill().send({
|
||||
// from: shop,
|
||||
// });
|
||||
|
||||
// shopBalance = await TestToken.methods.balanceOf(shop).call();
|
||||
// assert.equal(parseInt(shopBalance), TOTAL_SUPPLY - GIFT_AMOUNT);
|
||||
|
||||
// factoryBalance = await TestToken.methods.balanceOf(giftsBatchInstance._address).call();
|
||||
// assert.equal(parseInt(factoryBalance), 0);
|
||||
// }
|
||||
|
||||
// it("shop cannot kill contract before expirationTime", async function() {
|
||||
// await mineAt(NOW);
|
||||
// try {
|
||||
// await testKill();
|
||||
// assert.fail("redeem should have failed");
|
||||
// } catch(e) {
|
||||
// assert.match(e.message, /not expired yet/);
|
||||
// }
|
||||
// });
|
||||
|
||||
// it("shop can kill contract after expirationTime", async function() {
|
||||
// await mineAt(EXPIRATION_TIME);
|
||||
// await testKill();
|
||||
// });
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user