27 | )
28 |
29 | export default SearchBar
30 |
--------------------------------------------------------------------------------
/src/utils/transaction.js:
--------------------------------------------------------------------------------
1 | export const generateLikeTransaction = account => ({
2 | actions: [{
3 | account: 'tropical',
4 | name: 'like',
5 | authorization: [{
6 | actor: account,
7 | permission: 'active',
8 | }],
9 | data: {
10 | user: account,
11 | },
12 | }],
13 | })
14 |
15 | export const generateRentTransaction = (accountName, propertyName, serverKey, userKey, serverAuth, userAuth) => ({
16 | context_free_actions: [{
17 | account: 'tropical',
18 | name: 'check2fa',
19 | authorization: [],
20 | data: {
21 | user: accountName,
22 | property: propertyName,
23 | server_key: serverKey,
24 | user_key: userKey,
25 | server_auth: serverAuth,
26 | bearer_auth: userAuth,
27 | },
28 | }],
29 | actions: [{
30 | account: 'tropical',
31 | name: 'rent',
32 | authorization: [{
33 | actor: accountName,
34 | permission: 'active',
35 | }],
36 | data: {
37 | user: accountName,
38 | property: propertyName,
39 | },
40 | },
41 | ],
42 | })
43 |
44 | export const transactionConfig = { broadcast: true, expireSeconds: 300 }
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017-2019 block.one and its contributors. All rights reserved.
2 |
3 | The MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/eosio/contracts/eosio.token/eosio.token.contracts.md:
--------------------------------------------------------------------------------
1 |
4 | ---
5 | spec_version: 0.2.0
6 | title: Like a Property
7 | summary: Like a Tropical Example property
8 | icon: https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/Love_Heart_SVG.svg/265px-Love_Heart_SVG.svg.png#301991F0C25EE8EAA55F4CE940B9E5910560652A8D930C56D65C3C8987FF7DDB
9 | ---
10 | Liking this property will be visible to anyone who views your profile or searches your name.
11 | This like may result in the post owner’s property to be featured on the property owner’s most liked pages.
12 | Any usage of bots, macros, or any autonomous form of liking a specific person’s property would result in the investigation of like legitimacy for a post.
13 |
14 | rent
15 |
16 | ---
17 | spec_version: 0.2.0
18 | title: Rent a Property
19 | summary: Rent a Tropical Example property
20 | icon: https://https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Dollar_sign_in_circle.svg/240px-Dollar_sign_in_circle.svg.png#27F7CC5F628A8FC0B16680C141D58D42A1F49E3E38B1A4F67590C61F5D607CBF
21 | ---
22 | Renting a property requires 2FA and constitutes a binding agreement to pay the listed rental fee(s).
23 | Any usage of bots, macros, or any autonomous form of liking a specific person’s property would result in the investigation of like legitimacy for a post.
24 |
25 | check2fa
26 |
27 | ---
28 | spec_version: 0.2.0
29 | title: Validate the 2FA Token
30 | summary: Validate a WebAuthn second factor
31 | icon: https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/OOjs_UI_icon_key-ltr.svg/200px-OOjs_UI_icon_key-ltr.svg.png#0A1E2435DCAFDF4B34E60C65C570DCE30FAAC1862D7C5E139D188A6EAAF95014
32 | ---
33 | Any usage of bots, macros, or any autonomous form of liking a specific person’s property would result in the investigation of like legitimacy for a post.
34 |
35 | setsrvkey
36 |
37 | ---
38 | spec_version: 0.2.0
39 | title: Set the Root-of-trust
40 | summary: This is an administrative action that sets the respected "root of trust" key that counter signs 2FA
41 | icon: https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/OOjs_UI_icon_key-ltr.svg/200px-OOjs_UI_icon_key-ltr.svg.png#0A1E2435DCAFDF4B34E60C65C570DCE30FAAC1862D7C5E139D188A6EAAF95014
42 | ---
43 | Any usage of bots, macros, or any autonomous form of liking a specific person’s property would result in the investigation of like legitimacy for a post.
44 |
--------------------------------------------------------------------------------
/src/components/navigation/UserInfo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { UALContext } from 'ual-reactjs-renderer'
3 | import './UserInfo.scss'
4 |
5 | import UserDropdown from 'components/navigation/UserDropdown'
6 | import downArrow from 'assets/images/down-arrow.svg'
7 | import upArrow from 'assets/images/up-arrow.svg'
8 | import { onKeyUpEnter } from 'utils/keyPress'
9 |
10 | class UserInfo extends React.Component {
11 | _isMounted = false
12 |
13 | state = {
14 | showDropdown: false,
15 | accountName: '',
16 | }
17 |
18 | async componentDidMount() {
19 | this._isMounted = true
20 | const { activeUser } = this.context
21 | if (activeUser) {
22 | const accountName = await activeUser.getAccountName()
23 | if (this._isMounted) {
24 | this.setState({ accountName })
25 | }
26 | }
27 | }
28 |
29 | componentWillUnmount() {
30 | this._isMounted = false
31 | }
32 |
33 | toggleDropdown = () => {
34 | this.setState(prevState => ({
35 | showDropdown: !prevState.showDropdown,
36 | }))
37 | }
38 |
39 | static contextType = UALContext
40 |
41 | renderLogout = (enroll, enrolled) => (
42 |
43 |
125 | )
126 | }
127 | }
128 |
129 | export default Property
130 |
--------------------------------------------------------------------------------
/eosio/contracts/tropical/tropical.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | using namespace eosio;
7 |
8 | CONTRACT tropical : public contract {
9 | public:
10 | tropical(name self, name first_receiver, datastream ds)
11 | :contract(self, first_receiver, ds)
12 | ,configuration_singleton(get_self(), get_self().value)
13 | {}
14 |
15 | ACTION like( name user ) {
16 | print_f("You've liked a property on chain, %!\n", user);
17 | }
18 |
19 | /**
20 | * Global singleton that holds the current "root of trust"
21 | */
22 | TABLE config {
23 | public_key srvkey;
24 |
25 | EOSLIB_SERIALIZE( config, (srvkey) )
26 | };
27 |
28 | eosio::singleton< "config"_n, config > configuration_singleton;
29 |
30 | /**
31 | *
32 | * @param user
33 | * @param property
34 | * @return
35 | */
36 | ACTION rent( name user, name property ) {
37 | // enforce that the check2fa action is the first CFA
38 | //
39 | auto check2fa_action = get_action(0, 0);
40 |
41 | // unpack the first two parameters
42 | //
43 | auto second_factor_params = unpack>(check2fa_action.data);
44 |
45 | // validate that the 2FA was properly sent to this contract
46 | //
47 | check(check2fa_action.account == _self, "Malformed 2FA action, wrong account");
48 |
49 | // validate that the 2FA was propertly sent to the `check2fa` context-free action handler
50 | //
51 | check(check2fa_action.name == "check2fa"_n, "Malfomed 2FA action, wrong name");
52 |
53 | // validate that the 2FA was for this user and property
54 | //
55 | check(std::get<0>(second_factor_params) == user, "Malformed 2FA action, wrong user");
56 | check(std::get<1>(second_factor_params) == property, "Malfomed 2FA action, wrong property");
57 |
58 | // finally validate that the root of trust, the server_key, matches the chain state
59 | // this was not possible in a context free action
60 | //
61 | auto server_key = configuration_singleton.get().srvkey;
62 | check(std::get<2>(second_factor_params) == server_key, "Malfomed 2FA action, wrong root of trust");
63 |
64 | print_f("You've rented a % on chain, %!\n", property, user);
65 | }
66 |
67 | /**
68 | * Validate that a provided pair of signatures represents the provided user and property names as well as
69 | * a chain of trust for a user_key that terminates in a server_key
70 | *
71 | * This is a context-free action. This means it cannot access any chain state. It can only enforce the
72 | * consistency of the parameters passed to it. This implies that this action will succeed as long as
73 | * the user, property, and user_key are attested to by the server_key via various signatures.
74 | *
75 | * it *does not* validate the server_key
76 | *
77 | * @param user - the name of the user present in this 2fa assertion
78 | * @param property - the name of the property present in this 2fa assertion
79 | * @param server_key - the public key that is the root of trust for this assertion
80 | * @param user_key - a public key, trusted by `server_key`, to be in possessed by `user`
81 | * @param server_auth - a signature from the `server_key`
82 | * @param bearer_auth - a signature from the `user_key`
83 | */
84 | ACTION check2fa( name user, name property, public_key server_key, public_key user_key, signature server_auth, signature bearer_auth ) {
85 | // concatenate the serialized user name, property name, and user public key
86 | // as the "challenge" that the server would have signed
87 | //
88 | auto challenge = pack(std::forward_as_tuple(user, property, user_key));
89 |
90 | // hash the "challenge" into a signature digest that both the server and the user's WebAuthn authenticator
91 | // will sign in order to prove to the chain that there was a valid second factor ceremony
92 | //
93 | auto signature_digest = sha256(challenge.data(), challenge.size());
94 |
95 | // verify the provided signature from the server, this is something only an entity in possession of the
96 | // private `server_key` can have properly generated
97 | //
98 | assert_recover_key(signature_digest, server_auth, server_key);
99 |
100 | // verify the provided signature from the bearer, this is something only an entity in possession of the
101 | // private `user_key` can have properly generated and the `user_key` is attested to by the `server_key`
102 | // via the challenge digest
103 | //
104 | assert_recover_key(signature_digest, bearer_auth, user_key);
105 | }
106 |
107 | /**
108 | * Administrative action to set the root of trust, aka server key
109 | *
110 | * @param server_key - the public key that is the root of trust for this contract
111 | */
112 | ACTION setsrvkey(public_key server_key) {
113 | require_auth(_self);
114 | configuration_singleton.set({server_key}, _self);
115 | }
116 | };
117 |
--------------------------------------------------------------------------------
/IMPORTANT.md:
--------------------------------------------------------------------------------
1 | # Important Notice
2 |
3 | We (block.one and its affiliates) make available EOSIO and other software, updates, patches and documentation (collectively, Software) on a voluntary basis as a member of the EOSIO community. A condition of you accessing any Software, websites, articles, media, publications, documents or other material (collectively, Material) is your acceptance of the terms of this important notice.
4 |
5 | ## Software
6 | We are not responsible for ensuring the overall performance of Software or any related applications. Any test results or performance figures are indicative and will not reflect performance under all conditions. Software may contain components that are open sourced and subject to their own licenses; you are responsible for ensuring your compliance with those licenses.
7 |
8 | We make no representation, warranty, guarantee or undertaking in respect of Software, whether expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall we 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.
9 |
10 | Wallets and related components are complex software that require the highest levels of security. If incorrectly built or used, they may compromise users’ private keys and digital assets. Wallet applications and related components should undergo thorough security evaluations before being used. Only experienced developers should work with such Software.
11 |
12 | Material is not made available to any person or entity that is the subject of sanctions administered or enforced by any country or government or otherwise designated on any list of prohibited or restricted parties (including but not limited to the lists maintained by the United Nations Security Council, the U.S. Government, the European Union or its Member States, or other applicable government authority) or organized or resident in a country or territory that is the subject of country-wide or territory-wide sanctions. You represent and warrant that neither you nor any party having a direct or indirect beneficial interest in you or on whose behalf you are acting as agent or nominee is such a person or entity and you will comply with all applicable import, re-import, sanctions, anti-boycott, export, and re-export control laws and regulations. If this is not accurate or you do not agree, then you must immediately cease accessing our Material and delete all copies of Software.
13 |
14 | Any person using or offering Software in connection with providing software, goods or services to third parties shall advise such third parties of this important notice, including all limitations, restrictions and exclusions of liability.
15 |
16 | ## Trademarks
17 | Block.one, EOSIO, EOS, the heptahedron and associated logos and related marks are our trademarks. Other trademarks referenced in Material are the property of their respective owners.
18 |
19 | ## Third parties
20 | Any reference in Material to any third party or third-party product, resource or service is not an endorsement or recommendation by Block.one. We are not responsible for, and disclaim any and all responsibility and liability for, your use of or reliance on any of these resources. Third-party resources may be updated, changed or terminated at any time, so information in Material may be out of date or inaccurate.
21 |
22 | ## Forward-looking statements
23 | Please note that in making statements expressing Block.one’s vision, we do not guarantee anything, and all aspects of our vision are subject to change at any time and in all respects at Block.one’s sole discretion, with or without notice. We call these “forward-looking statements”, which includes statements on our website and in other Material, other than statements of historical facts, such as statements regarding EOSIO’s development, expected performance, and future features, or our business strategy, plans, prospects, developments and objectives. These statements are only predictions and reflect Block.one’s current beliefs and expectations with respect to future events; they are based on assumptions and are subject to risk, uncertainties and change at any time.
24 |
25 | We operate in a rapidly changing environment and new risks emerge from time to time. Given these risks and uncertainties, you are cautioned not to rely on these forward-looking statements. Actual results, performance or events may differ materially from what is predicted in the forward-looking statements. Some of the factors that could cause actual results, performance or events to differ materially from the forward-looking statements include, without limitation: technical feasibility and barriers; market trends and volatility; continued availability of capital, financing and personnel; product acceptance; the commercial success of any new products or technologies; competition; government regulation and laws; and general economic, market or business conditions.
26 |
27 | All statements are valid only as of the date of first posting and Block.one is under no obligation to, and expressly disclaims any obligation to, update or alter any statements, whether as a result of new information, subsequent events or otherwise. Nothing in any Material constitutes technological, financial, investment, legal or other advice, either in general or with regard to any particular situation or implementation. Please consult with experts in appropriate areas before implementing or utilizing anything contained in Material.
28 |
--------------------------------------------------------------------------------
/src/utils/webauthn.js:
--------------------------------------------------------------------------------
1 | import base64url from 'base64url'
2 | import { Serialize, Numeric } from 'eosjs'
3 | import { ec as EC } from 'elliptic'
4 |
5 | // taken from the
6 | const formatWebauthnPubkey = (pubkey) => {
7 | const clientDataStr = String.fromCharCode.apply(null, new Uint8Array(pubkey.clientDataJSON))
8 | return {
9 | attestationObject: base64url.encode(pubkey.attestationObject),
10 | clientData: JSON.parse(clientDataStr),
11 | }
12 | }
13 |
14 | const decodeWebauthnSignature = (assertion, key) => {
15 | const e = new EC('p256')
16 | const fixup = (x) => {
17 | const a = Array.from(x)
18 | while (a.length < 32) a.unshift(0)
19 | while (a.length > 32) if (a.shift() !== 0) throw new Error('Signature has an r or s that is too big')
20 | return new Uint8Array(a)
21 | }
22 |
23 | const der = new Serialize.SerialBuffer({ array: new Uint8Array(assertion.signature) })
24 | if (der.get() !== 0x30) throw new Error('Signature missing DER prefix')
25 | if (der.get() !== der.array.length - 2) throw new Error('Signature has bad length')
26 | if (der.get() !== 0x02) throw new Error('Signature has bad r marker')
27 | const r = fixup(der.getUint8Array(der.get()))
28 | if (der.get() !== 0x02) throw new Error('Signature has bad s marker')
29 | const s = fixup(der.getUint8Array(der.get()))
30 |
31 | const pubkeyData = Numeric.stringToPublicKey(key).data.subarray(0, 33)
32 | const pubKey = e.keyFromPublic(pubkeyData).getPublic()
33 | const signedData = Buffer.concat([
34 | Buffer.from(assertion.authenticatorData),
35 | Buffer.from(e.hash().update(Buffer.from(assertion.clientDataJSON)).digest()),
36 | ])
37 | const hash = Buffer.from(e.hash().update(signedData).digest())
38 | const recid = e.getKeyRecoveryParam(hash, Buffer.from(assertion.signature), pubKey)
39 |
40 | const sigData = new Serialize.SerialBuffer()
41 | sigData.push(recid + 27 + 4)
42 | sigData.pushArray(r)
43 | sigData.pushArray(s)
44 | sigData.pushBytes(new Uint8Array(assertion.authenticatorData))
45 | sigData.pushBytes(new Uint8Array(assertion.clientDataJSON))
46 |
47 | const sig = Numeric.signatureToString({
48 | type: Numeric.KeyType.wa,
49 | data: sigData.asUint8Array().slice(),
50 | })
51 |
52 | return sig
53 | }
54 |
55 | export const generateWebauthnPubkey = async (accountName) => {
56 | const createCredentialOptions = {
57 | // Format of new credentials is publicKey
58 | publicKey: {
59 | // Relying Party
60 | rp: {
61 | name: 'Tropical Stay',
62 | id: window.location.hostname,
63 | },
64 | // Cryptographic challenge from the server
65 | challenge: new Uint8Array(26),
66 | // User
67 | user: {
68 | id: new Uint8Array(16),
69 | name: accountName,
70 | displayName: accountName,
71 | },
72 | // Requested format of new keypair
73 | pubKeyCredParams: [{
74 | type: 'public-key',
75 | alg: -7,
76 | }],
77 | timeout: 60000,
78 | attestation: 'direct',
79 | },
80 | }
81 |
82 | const webauthnResp = await navigator.credentials.create(createCredentialOptions)
83 | return formatWebauthnPubkey(webauthnResp.response)
84 | }
85 |
86 | export const enrollWebauthnPubkey = async (accountName, webauthnPublicKey) => {
87 | const payload = {
88 | accountName,
89 | webauthnPublicKey,
90 | hostname: window.location.hostname,
91 | }
92 |
93 | const enrollResponse = await fetch('/api/enroll', {
94 | method: 'POST',
95 | headers: {
96 | 'Content-Type': 'application/json',
97 | },
98 | body: JSON.stringify(payload),
99 | })
100 |
101 | const enrollResult = await enrollResponse.json()
102 | if (!enrollResult.status || enrollResult.status !== 'ok') {
103 | throw new Error('Enrollment failed')
104 | }
105 | }
106 |
107 | export const generateRentChallenge = async (accountName, propertyName) => {
108 | const payload = {
109 | accountName,
110 | propertyName,
111 | }
112 |
113 | const resp = await fetch('/api/generateRentChallenge', {
114 | method: 'POST',
115 | headers: {
116 | 'Content-Type': 'application/json',
117 | },
118 | body: JSON.stringify(payload),
119 | })
120 |
121 | const result = await resp.json()
122 | if (!result.status || result.status !== 'ok') {
123 | throw new Error('Enrollment failed')
124 | }
125 |
126 | return result
127 | }
128 |
129 | export const signRentChallenge = async (accountName, propertyName, challenge) => {
130 | const e = new EC('p256')
131 | const challengeBuffer = new Serialize.SerialBuffer()
132 | challengeBuffer.pushName(accountName)
133 | challengeBuffer.pushName(propertyName)
134 | challengeBuffer.pushPublicKey(challenge.userKey)
135 | const sigData = challengeBuffer.asUint8Array()
136 | // const sigDigest = Buffer.from(ecc.sha256(sigData), 'hex')
137 | const sigDigest = Buffer.from(e.hash().update(sigData).digest())
138 | const getCredentialOptions = {
139 | publicKey: {
140 | timeout: 60000,
141 | allowCredentials: [{
142 | id: base64url.toBuffer(challenge.credentialID),
143 | type: 'public-key',
144 | }],
145 | challenge: sigDigest,
146 | },
147 | }
148 |
149 | const webauthnResp = await navigator.credentials.get(getCredentialOptions)
150 | return decodeWebauthnSignature(webauthnResp.response, challenge.userKey)
151 | }
152 |
153 | export const canUseWebAuthN = () => window.location.protocol.replace(/:$/, '') === 'https'
154 |
--------------------------------------------------------------------------------
/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read http://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.1/8 is considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl)
104 | .then(response => {
105 | // Ensure service worker exists, and that we really are getting a JS file.
106 | const contentType = response.headers.get('content-type');
107 | if (
108 | response.status === 404 ||
109 | (contentType != null && contentType.indexOf('javascript') === -1)
110 | ) {
111 | // No service worker found. Probably a different app. Reload the page.
112 | navigator.serviceWorker.ready.then(registration => {
113 | registration.unregister().then(() => {
114 | window.location.reload();
115 | });
116 | });
117 | } else {
118 | // Service worker found. Proceed as normal.
119 | registerValidSW(swUrl, config);
120 | }
121 | })
122 | .catch(() => {
123 | console.log(
124 | 'No internet connection found. App is running in offline mode.'
125 | );
126 | });
127 | }
128 |
129 | export function unregister() {
130 | if ('serviceWorker' in navigator) {
131 | navigator.serviceWorker.ready.then(registration => {
132 | registration.unregister();
133 | });
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/eosio/contracts/eosio.bios-v1.8.3/eosio.bios.contracts.md:
--------------------------------------------------------------------------------
1 |
35 |
36 | ---
37 | spec_version: "0.2.0"
38 | title: Link Action to Permission
39 | summary: '{{nowrap account}} sets the minimum required permission for the {{#if type}}{{nowrap type}} action of the{{/if}} {{nowrap code}} contract to {{nowrap requirement}}'
40 | icon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f
41 | ---
42 |
43 | {{account}} sets the minimum required permission for the {{#if type}}{{type}} action of the{{/if}} {{code}} contract to {{requirement}}.
44 |
45 | {{#if type}}{{else}}Any links explicitly associated to specific actions of {{code}} will take precedence.{{/if}}
46 |
47 |
newaccount
48 |
49 | ---
50 | spec_version: "0.2.0"
51 | title: Create New Account
52 | summary: '{{nowrap creator}} creates a new account with the name {{nowrap name}}'
53 | icon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f
54 | ---
55 |
56 | {{creator}} creates a new account with the name {{name}} and the following permissions:
57 |
58 | owner permission with authority:
59 | {{to_json owner}}
60 |
61 | active permission with authority:
62 | {{to_json active}}
63 |
64 |
reqactivated
65 |
66 | ---
67 | spec_version: "0.2.0"
68 | title: Assert Protocol Feature Activation
69 | summary: 'Assert that protocol feature {{nowrap feature_digest}} has been activated'
70 | icon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/admin.png#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e
71 | ---
72 |
73 | Assert that the protocol feature with a digest of {{feature_digest}} has been activated.
74 |
75 |
reqauth
76 |
77 | ---
78 | spec_version: "0.2.0"
79 | title: Assert Authorization
80 | summary: 'Assert that authorization by {{nowrap from}} is provided'
81 | icon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f
82 | ---
83 |
84 | Assert that authorization by {{from}} is provided.
85 |
86 |
setabi
87 |
88 | ---
89 | spec_version: "0.2.0"
90 | title: Deploy Contract ABI
91 | summary: 'Deploy contract ABI on account {{nowrap account}}'
92 | icon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f
93 | ---
94 |
95 | Deploy the ABI file associated with the contract on account {{account}}.
96 |
97 |
setalimits
98 |
99 | ---
100 | spec_version: "0.2.0"
101 | title: Adjust Resource Limits of Account
102 | summary: 'Adjust resource limits of account {{nowrap account}}'
103 | icon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/admin.png#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e
104 | ---
105 |
106 | {{$action.account}} updates {{account}}’s resource limits to have a RAM quota of {{ram_bytes}} bytes, a NET bandwidth quota of {{net_weight}} and a CPU bandwidth quota of {{cpu_weight}}.
107 |
108 |
161 |
162 | ---
163 | spec_version: "0.2.0"
164 | title: Unlink Action from Permission
165 | summary: '{{nowrap account}} unsets the minimum required permission for the {{#if type}}{{nowrap type}} action of the{{/if}} {{nowrap code}} contract'
166 | icon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f
167 | ---
168 |
169 | {{account}} removes the association between the {{#if type}}{{type}} action of the{{/if}} {{code}} contract and its minimum required permission.
170 |
171 | {{#if type}}{{else}}This will not remove any links explicitly associated to specific actions of {{code}}.{{/if}}
172 |
173 |
updateauth
174 |
175 | ---
176 | spec_version: "0.2.0"
177 | title: Modify Account Permission
178 | summary: 'Add or update the {{nowrap permission}} permission of {{nowrap account}}'
179 | icon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f
180 | ---
181 |
182 | Modify, and create if necessary, the {{permission}} permission of {{account}} to have a parent permission of {{parent}} and the following authority:
183 | {{to_json auth}}
184 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Tropical Example
2 |
3 | Interested in contributing? That's awesome! Here are some guidelines to get started quickly and easily:
4 |
5 | - [Contributing to Tropical Example](#contributing-to-tropical-example)
6 | - [Reporting An Issue](#reporting-an-issue)
7 | - [Bug Reports](#bug-reports)
8 | - [Feature Requests](#feature-requests)
9 | - [Change Requests](#change-requests)
10 | - [Working on Tropical Example](#working-on-tropical-example)
11 | - [Feature Branches](#feature-branches)
12 | - [Submitting Pull Requests](#submitting-pull-requests)
13 | - [Testing and Quality Assurance](#testing-and-quality-assurance)
14 | - [Conduct](#conduct)
15 | - [Contributor License & Acknowledgments](#contributor-license--acknowledgments)
16 | - [References](#references)
17 |
18 | ## Reporting An Issue
19 |
20 | If you're about to raise an issue because you think you've found a problem with Tropical Example, or you'd like to make a request for a new feature in the codebase, or any other reason… please read this first.
21 |
22 | The GitHub issue tracker is the preferred channel for [bug reports](#bug-reports), [feature requests](#feature-requests), and [submitting pull requests](#submitting-pull-requests), but please respect the following restrictions:
23 |
24 | * Please **search for existing issues**. Help us keep duplicate issues to a minimum by checking to see if someone has already reported your problem or requested your idea.
25 |
26 | * Please **be civil**. Keep the discussion on topic and respect the opinions of others. See also our [Contributor Code of Conduct](#conduct).
27 |
28 | ### Bug Reports
29 |
30 | A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are extremely helpful - thank you!
31 |
32 | Guidelines for bug reports:
33 |
34 | 1. **Use the GitHub issue search** — check if the issue has already been
35 | reported.
36 |
37 | 1. **Check if the issue has been fixed** — look for [closed issues in the
38 | current milestone](https://github.com/EOSIO/tropical-example-web-app/issues?q=is%3Aissue+is%3Aclosed) or try to reproduce it
39 | using the latest `develop` branch.
40 |
41 | A good bug report shouldn't leave others needing to chase you up for more information. Be sure to include the details of your environment and relevant tests that demonstrate the failure.
42 |
43 | [Report a bug](https://github.com/EOSIO/tropical-example-web-app/issues/new?title=Bug%3A)
44 |
45 | ### Feature Requests
46 |
47 | Feature requests are welcome. Before you submit one be sure to have:
48 |
49 | 1. **Use the GitHub search** and check the feature hasn't already been requested.
50 | 1. Take a moment to think about whether your idea fits with the scope and aims of the project.
51 | 1. Remember, it's up to *you* to make a strong case to convince the project's leaders of the merits of this feature. Please provide as much detail and context as possible, this means explaining the use case and why it is likely to be common.
52 |
53 | ### Change Requests
54 |
55 | Change requests cover both architectural and functional changes to how Tropical Example works. If you have an idea for a new or different dependency, a refactor, or an improvement to a feature, etc - please be sure to:
56 |
57 | 1. **Use the GitHub search** and check someone else didn't get there first
58 | 1. Take a moment to think about the best way to make a case for, and explain what you're thinking. Are you sure this shouldn't really be
59 | a [bug report](#bug-reports) or a [feature request](#feature-requests)? Is it really one idea or is it many? What's the context? What problem are you solving? Why is what you are suggesting better than what's already there?
60 |
61 | ## Working on Tropical Example
62 |
63 | Code contributions are welcome and encouraged! If you are looking for a good place to start, check out the [good first issue](https://github.com/EOSIO/tropical-example-web-app/labels/good%20first%20issue) label in GitHub issues.
64 |
65 | Also, please follow these guidelines when submitting code:
66 |
67 | ### Feature Branches
68 |
69 | To get it out of the way:
70 |
71 | - **[develop](https://github.com/EOSIO/tropical-example-web-app/tree/develop)** is the development branch. All work on the next release happens here so you should generally branch off `develop`. Do **NOT** use this branch for a production site.
72 | - **[master](https://github.com/EOSIO/tropical-example-web-app)** contains the latest release of Tropical Example. This branch may be used in production. Do **NOT** use this branch to work on Tropical Example's source.
73 |
74 | ### Submitting Pull Requests
75 |
76 | Pull requests are awesome. If you're looking to raise a PR for something which doesn't have an open issue, please think carefully about [raising an issue](#reporting-an-issue) which your PR can close, especially if you're fixing a bug. This makes it more likely that there will be enough information available for your PR to be properly tested and merged.
77 |
78 | ### Testing and Quality Assurance
79 |
80 | Never underestimate just how useful quality assurance is. If you're looking to get involved with the code base and don't know where to start, checking out and testing a pull request is one of the most useful things you could do.
81 |
82 | Essentially, [check out the latest develop branch](#working-on-tropical-example), take it for a spin, and if you find anything odd, please follow the [bug report guidelines](#bug-reports) and let us know!
83 |
84 | ## Conduct
85 |
86 | While contributing, please be respectful and constructive, so that participation in our project is a positive experience for everyone.
87 |
88 | Examples of behavior that contributes to creating a positive environment include:
89 | - Using welcoming and inclusive language
90 | - Being respectful of differing viewpoints and experiences
91 | - Gracefully accepting constructive criticism
92 | - Focusing on what is best for the community
93 | - Showing empathy towards other community members
94 |
95 | Examples of unacceptable behavior include:
96 | - The use of sexualized language or imagery and unwelcome sexual attention or advances
97 | - Trolling, insulting/derogatory comments, and personal or political attacks
98 | - Public or private harassment
99 | - Publishing others’ private information, such as a physical or electronic address, without explicit permission
100 | - Other conduct which could reasonably be considered inappropriate in a professional setting
101 |
102 |
103 |
104 | ## Contributor License & Acknowledgments
105 |
106 | Whenever you make a contribution to this project, you license your contribution under the same terms as set out in LICENSE, and you represent and warrant that you have the right to license your contribution under those terms. Whenever you make a contribution to this project, you also certify in the terms of the Developer’s Certificate of Origin set out below:
107 |
108 | ```
109 | Developer Certificate of Origin
110 | Version 1.1
111 |
112 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
113 | 1 Letterman Drive
114 | Suite D4700
115 | San Francisco, CA, 94129
116 |
117 | Everyone is permitted to copy and distribute verbatim copies of this
118 | license document, but changing it is not allowed.
119 |
120 |
121 | Developer's Certificate of Origin 1.1
122 |
123 | By making a contribution to this project, I certify that:
124 |
125 | (a) The contribution was created in whole or in part by me and I
126 | have the right to submit it under the open source license
127 | indicated in the file; or
128 |
129 | (b) The contribution is based upon previous work that, to the best
130 | of my knowledge, is covered under an appropriate open source
131 | license and I have the right under that license to submit that
132 | work with modifications, whether created in whole or in part
133 | by me, under the same open source license (unless I am
134 | permitted to submit under a different license), as indicated
135 | in the file; or
136 |
137 | (c) The contribution was provided directly to me by some other
138 | person who certified (a), (b) or (c) and I have not modified
139 | it.
140 |
141 | (d) I understand and agree that this project and the contribution
142 | are public and that a record of the contribution (including all
143 | personal information I submit with it, including my sign-off) is
144 | maintained indefinitely and may be redistributed consistent with
145 | this project or the open source license(s) involved.
146 | ```
147 |
148 | ## References
149 |
150 | * Overall CONTRIB adapted from https://github.com/mathjax/MathJax/blob/master/CONTRIBUTING.md
151 | * Conduct section adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
152 |
--------------------------------------------------------------------------------
/eosio/scripts/deploy_contracts.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | NODEOS_RUNNING=$1
3 | RUNNING_IN_GITPOD=$2
4 |
5 | set -m
6 |
7 | # CAUTION: Never use these development keys for a production account!
8 | # Doing so will most certainly result in the loss of access to your account, these private keys are publicly known.
9 | SYSTEM_ACCOUNT_PRIVATE_KEY="5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"
10 | SYSTEM_ACCOUNT_PUBLIC_KEY="EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
11 |
12 | TROPICAL_EXAMPLE_ACCOUNT_PRIVATE_KEY="5Jh6jf9g1UzcWrMMsgqd5GrTCgzeKkh5yT7EUZbiU7wB7k4Ayx1"
13 | TROPICAL_EXAMPLE_ACCOUNT_PUBLIC_KEY="EOS6bRs6knaaHyvpVXd5EgAPoxrZkkeDv89M1jidHCt86W5rkwr1q"
14 |
15 | EXAMPLE_ACCOUNT_PRIVATE_KEY="5KkXYBUb7oXrq9cvEYT3HXsoHvaC2957VKVftVRuCy7Z7LyUcQB"
16 | EXAMPLE_ACCOUNT_PUBLIC_KEY="EOS6TWM95TUqpgcjYnvXSK5kBsi6LryWRxmcBaULVTvf5zxkaMYWf"
17 |
18 | if [ -z "$RUNNING_IN_GITPOD" ]; then
19 | echo "Running locally..."
20 | ROOT_DIR="/opt"
21 | CONTRACTS_DIR="$ROOT_DIR/eosio/bin/contracts"
22 | BLOCKCHAIN_DATA_DIR=/root/.local/share
23 | BLOCKCHAIN_CONFIG_DIR=/opt/eosio/bin/config-dir
24 | WALLET_DIR="/root/eosio-wallet/"
25 | else
26 | echo "Running in Gitpod..."
27 | ROOT_DIR="/home/gitpod"
28 | CONTRACTS_DIR="$ROOT_DIR/contracts"
29 | BLOCKCHAIN_DATA_DIR=$ROOT_DIR/eosio/chain/data
30 | BLOCKCHAIN_CONFIG_DIR=$ROOT_DIR/eosio/chain/config
31 | WALLET_DIR="$ROOT_DIR/eosio-wallet"
32 | fi
33 |
34 | mkdir -p $ROOT_DIR/bin
35 |
36 | # Set PATH
37 | PATH="$PATH:$ROOT_DIR/bin:$ROOT_DIR/bin/scripts"
38 | GITPOD_WORKSPACE_ROOT="/workspace/tropical-example-web-app"
39 | CONFIG_DIR="$ROOT_DIR/bin/config-dir"
40 |
41 | function start_wallet {
42 | echo "Starting the wallet"
43 | rm -rf $WALLET_DIR
44 | mkdir -p $WALLET_DIR
45 | nohup keosd --unlock-timeout 999999999 --wallet-dir $WALLET_DIR --http-server-address 127.0.0.1:8900 2>&1 &
46 | sleep 1s
47 | wallet_password=$(cleos wallet create --to-console | awk 'FNR > 3 { print $1 }' | tr -d '"')
48 | echo $wallet_password > "$CONFIG_DIR"/keys/default_wallet_password.txt
49 |
50 | cleos wallet import --private-key $SYSTEM_ACCOUNT_PRIVATE_KEY
51 | }
52 |
53 | function post_preactivate {
54 | curl -X POST http://127.0.0.1:8888/v1/producer/schedule_protocol_feature_activations -d '{"protocol_features_to_activate": ["0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd"]}'
55 | }
56 |
57 | # $1 feature disgest to activate
58 | function activate_feature {
59 | cleos push action eosio activate '["'"$1"'"]' -p eosio
60 | if [ $? -ne 0 ]; then
61 | exit 1
62 | fi
63 | }
64 |
65 | # $1 account name
66 | # $2 contract directory
67 | # $3 wasm file name
68 | # $4 abi file name
69 | function setcode {
70 | retry_count="4"
71 |
72 | while [ $retry_count -gt 0 ]; do
73 | cleos set contract $1 $2 $3 $4 -p $1@active
74 | if [ $? -eq 0 ]; then
75 | break
76 | fi
77 |
78 | echo "setcode failed retrying..."
79 | sleep 1s
80 | retry_count=$[$retry_count-1]
81 | done
82 |
83 | if [ $retry_count -eq 0 ]; then
84 | echo "setcode failed too many times, bailing."
85 | exit 1
86 | fi
87 | }
88 |
89 | # $1 - parent folder where smart contract directory is located
90 | # $2 - smart contract name
91 | # $3 - account name
92 | function deploy_system_contract {
93 | # Unlock the wallet, ignore error if already unlocked
94 | cleos wallet unlock --password $(cat "$CONFIG_DIR"/keys/default_wallet_password.txt) || true
95 |
96 | echo "Deploying the $2 contract in path: $CONTRACTS_DIR/$1/$2/src"
97 |
98 | # Move into contracts /src directory
99 | cd "$CONTRACTS_DIR/$1/$2/src"
100 |
101 | # Compile the smart contract to wasm and abi files using the EOSIO.CDT (Contract Development Toolkit)
102 | # https://github.com/EOSIO/eosio.cdt
103 | eosio-cpp -abigen "$2.cpp" -o "$2.wasm" -I ../include
104 |
105 | # Move back into the executable directory
106 | cd $CONTRACTS_DIR
107 |
108 | # Set (deploy) the compiled contract to the blockchain
109 | setcode $3 "$CONTRACTS_DIR/$1/$2/src" "$2.wasm" "$2.abi"
110 | }
111 |
112 | function deploy_1.8.x_bios {
113 | # Unlock the wallet, ignore error if already unlocked
114 | cleos wallet unlock --password $(cat "$CONFIG_DIR"/keys/default_wallet_password.txt) || true
115 |
116 | echo "Deploying the v1.8.3 eosio.bios contract in path: $CONTRACTS_DIR/$1"
117 |
118 | # Move back into the executable directory
119 | cd $CONTRACTS_DIR
120 |
121 | # Set (deploy) the compiled contract to the blockchain
122 | setcode $3 "$CONTRACTS_DIR/$1" "$2.wasm" "$2.abi"
123 | }
124 |
125 | # $1 - account name
126 | # $2 - public key
127 | # $3 - private key
128 | function create_account {
129 | cleos wallet import --private-key $3
130 | cleos create account eosio $1 $2
131 | }
132 |
133 | # $1 - smart contract name
134 | # $2 - account name
135 | function deploy_app_contract {
136 | # Unlock the wallet, ignore error if already unlocked
137 | cleos wallet unlock --password $(cat "$CONFIG_DIR"/keys/default_wallet_password.txt) || true
138 |
139 | echo "Deploying the $1 contract"
140 |
141 | # Compile the smart contract to wasm and abi files using the EOSIO.CDT (Contract Development Toolkit)
142 | # https://github.com/EOSIO/eosio.cdt
143 |
144 | # Move into contracts directory
145 | cd "$CONTRACTS_DIR/$1/"
146 | (
147 | if [ ! -f "$1.wasm" ]; then
148 | eosio-cpp -abigen "$1.cpp" -o "$1.wasm" -I ./
149 | else
150 | echo "Using pre-built contract..."
151 | fi
152 | ) &&
153 | # Move back into the executable directory
154 | cd $CONTRACTS_DIR
155 |
156 | # Set (deploy) the compiled contract to the blockchain
157 | setcode $2 "$CONTRACTS_DIR/$1/" "$1.wasm" "$1.abi"
158 |
159 | # Set the root of trust for the contract
160 | cleos push action $2 setsrvkey '["'"$TROPICAL_EXAMPLE_ACCOUNT_PUBLIC_KEY"'"]' -p $2
161 |
162 | }
163 |
164 | function issue_sys_tokens {
165 | echo "Issuing SYS tokens"
166 | cleos push action eosio.token create '["eosio", "10000000000.0000 SYS"]' -p eosio.token
167 | cleos push action eosio.token issue '["eosio", "5000000000.0000 SYS", "Half of available supply"]' -p eosio
168 | }
169 |
170 | # $1 - account name
171 | function transfer_sys_tokens {
172 | cleos transfer eosio $1 "1000000.0000 SYS"
173 | }
174 |
175 | # $1 - chain id
176 | # $2 - chain name
177 | # $3 - icon hash
178 | function assert_set_chain {
179 | echo "Setting $2 chain"
180 | cleos push action eosio.assert setchain "[ "\""$1"\"", "\""$2"\"", "\""$3"\"" ]" -p eosio@active
181 | }
182 |
183 | # $1 - account name
184 | # $2 - domain
185 | # $3 - appmeta
186 | # $4 - whitelist
187 | function assert_register_manifest {
188 | echo "Registering $1 manifest"
189 | cleos push action eosio.assert add.manifest "[ "\""$1"\"", "\""$2"\"", "\""$3"\"", $4 ]" -p $1@active
190 | }
191 |
192 | # Move into the executable directory
193 | cd $ROOT_DIR/bin/
194 | mkdir -p $CONFIG_DIR
195 | mkdir -p $BLOCKCHAIN_DATA_DIR
196 | mkdir -p $BLOCKCHAIN_CONFIG_DIR
197 |
198 | if [ -z "$NODEOS_RUNNING" ]; then
199 | echo "Starting the chain for setup"
200 | nodeos -e -p eosio \
201 | --data-dir $BLOCKCHAIN_DATA_DIR \
202 | --config-dir $BLOCKCHAIN_CONFIG_DIR \
203 | --http-validate-host=false \
204 | --plugin eosio::producer_api_plugin \
205 | --plugin eosio::chain_api_plugin \
206 | --plugin eosio::http_plugin \
207 | --http-server-address=0.0.0.0:8888 \
208 | --access-control-allow-origin=* \
209 | --contracts-console \
210 | --max-transaction-time=100000 \
211 | --verbose-http-errors &
212 | fi
213 |
214 | mkdir -p "$CONFIG_DIR"/keys
215 |
216 | sleep 1s
217 |
218 | echo "Waiting for the chain to finish startup"
219 | until curl localhost:8888/v1/chain/get_info
220 | do
221 | echo "Still waiting"
222 | sleep 1s
223 | done
224 |
225 | # Sleep for 2s to allow time for 4 blocks to be created so we have blocks to reference when sending transactions
226 | sleep 2s
227 | echo "Creating accounts and deploying contracts"
228 |
229 | start_wallet
230 |
231 | if [ ! -z "$RUNNING_IN_GITPOD" ]; then
232 | echo "INSTALLING CONTRACTS"
233 | mkdir -p $CONTRACTS_DIR
234 | mkdir -p $ROOT_DIR/downloads
235 |
236 | echo "INSTALLING EOSIO.CONTRACTS"
237 | wget https://github.com/EOSIO/eosio.contracts/archive/v1.9.0.tar.gz
238 | mkdir -p $ROOT_DIR/downloads/eosio.contracts-1.9.0
239 | mkdir -p $CONTRACTS_DIR/eosio.contracts
240 | tar xvzf ./v1.9.0.tar.gz -C $ROOT_DIR/downloads/eosio.contracts-1.9.0
241 | mv $ROOT_DIR/downloads/eosio.contracts-1.9.0/eosio.contracts-1.9.0/* $CONTRACTS_DIR/eosio.contracts
242 | rm -rf $ROOT_DIR/downloads/eosio.contracts-1.9.0
243 | rm ./v1.9.0.tar.gz
244 |
245 | echo "INSTALLING EOSIO.ASSERT CONTRACT"
246 | wget https://github.com/EOSIO/eosio.assert/archive/v0.1.0.tar.gz
247 | mkdir -p $ROOT_DIR/downloads/eosio.assert
248 | mkdir -p $CONTRACTS_DIR/eosio.assert
249 | tar xvzf ./v0.1.0.tar.gz -C $ROOT_DIR/downloads/eosio.assert
250 | mv $ROOT_DIR/downloads/eosio.assert/eosio.assert-0.1.0/* $CONTRACTS_DIR/eosio.assert
251 | rm -rf $ROOT_DIR/downloads/eosio.assert
252 | rm ./v0.1.0.tar.gz
253 |
254 | echo "COPYING APP CONTRACT"
255 | echo "GITPOD_WORKSPACE_ROOT: $GITPOD_WORKSPACE_ROOT"
256 | cp $GITPOD_WORKSPACE_ROOT/eosio/contracts/eosio.token/eosio.token.contracts.md $CONTRACTS_DIR/eosio.contracts/contracts/eosio.token/src
257 | mkdir -p $CONTRACTS_DIR/eosio.bios-v1.8.3
258 | cp $GITPOD_WORKSPACE_ROOT/eosio/contracts/eosio.bios-v1.8.3/* $CONTRACTS_DIR/eosio.bios-v1.8.3/
259 | mkdir -p $CONTRACTS_DIR/tropical
260 | cp $GITPOD_WORKSPACE_ROOT/eosio/contracts/tropical/* $CONTRACTS_DIR/tropical/
261 | fi
262 |
263 | # preactivate concensus upgrades
264 | post_preactivate
265 |
266 | # Create accounts and deploy contracts
267 | # eosio.assert
268 | create_account eosio.assert $SYSTEM_ACCOUNT_PUBLIC_KEY $SYSTEM_ACCOUNT_PRIVATE_KEY
269 | deploy_system_contract eosio.assert eosio.assert eosio.assert
270 |
271 | # eosio.bios
272 |
273 | deploy_1.8.x_bios eosio.bios-v1.8.3 eosio.bios eosio
274 |
275 | activate_feature "299dcb6af692324b899b39f16d5a530a33062804e41f09dc97e9f156b4476707"
276 |
277 | deploy_system_contract eosio.contracts/contracts eosio.bios eosio
278 |
279 | # eosio.token
280 | create_account eosio.token $SYSTEM_ACCOUNT_PUBLIC_KEY $SYSTEM_ACCOUNT_PRIVATE_KEY
281 | deploy_system_contract eosio.contracts/contracts eosio.token eosio.token
282 | issue_sys_tokens
283 |
284 | # activate Webauthn support
285 | activate_feature "4fca8bd82bbd181e714e283f83e1b45d95ca5af40fb89ad3977b653c448f78c2"
286 |
287 | # tropical
288 | create_account tropical $TROPICAL_EXAMPLE_ACCOUNT_PUBLIC_KEY $TROPICAL_EXAMPLE_ACCOUNT_PRIVATE_KEY
289 | deploy_app_contract tropical tropical
290 | transfer_sys_tokens tropical
291 |
292 | # example
293 | create_account example $EXAMPLE_ACCOUNT_PUBLIC_KEY $EXAMPLE_ACCOUNT_PRIVATE_KEY
294 | transfer_sys_tokens example
295 |
296 | # eosio.assert actions
297 | # Set chain
298 | assert_set_chain "cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f" "Local Chain" "8ae3ccb19f3a89a8ea21f6c5e18bd2bc8f00c379411a2d9319985dad2db6243e"
299 |
300 | # Register tropical manifest
301 | # If running in Gitpod, we need to alter the URLs
302 | CONTRACT_NAME="tropical"
303 | MANIFEST="[{ "\""contract"\"": "\""tropical"\"", "\""action"\"": "\""like"\"" },{ "\""contract"\"": "\""tropical"\"", "\""action"\"": "\""rent"\"" },{ "\""contract"\"": "\""tropical"\"", "\""action"\"": "\""check2fa"\"" }, { "\""contract"\"": "\""eosio.assert"\"", "\""action"\"": "\""require"\"" }]"
304 | if [ -z "$RUNNING_IN_GITPOD" ]; then
305 | APP_DOMAIN="https://localhost:3000"
306 | APPMETA="https://localhost:3000/app-metadata.json#bc677523fca562e307343296e49596e25cb14aac6b112a9428a42119da9f65fa"
307 | else
308 | GP_URL=$(gp url 8000)
309 | APP_DOMAIN="${GP_URL}"
310 | APPMETA="${GP_URL}/app-metadata.json#bc677523fca562e307343296e49596e25cb14aac6b112a9428a42119da9f65fa"
311 | fi
312 | assert_register_manifest $CONTRACT_NAME $APP_DOMAIN $APPMETA "$MANIFEST"
313 |
314 | echo "All done initializing the blockchain"
315 |
316 | # If running in Gitpod, we *don't* want to shutdown the blockchain; we'll leave it running in the terminal window.
317 | if [ -z "$RUNNING_IN_GITPOD" ]; then
318 | if [[ -z $NODEOS_RUNNING ]]; then
319 | echo "Shut down Nodeos, sleeping for 2 seconds to allow time for at least 4 blocks to be created after deploying contracts"
320 | sleep 2s
321 | kill %1
322 | fg %1
323 | fi
324 | fi
325 |
--------------------------------------------------------------------------------
/src/assets/images/tropical-background.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/eosio/contracts/eosio.bios-v1.8.3/eosio.bios.abi:
--------------------------------------------------------------------------------
1 | {
2 | "____comment": "This file was generated with eosio-abigen. DO NOT EDIT ",
3 | "version": "eosio::abi/1.1",
4 | "types": [],
5 | "structs": [
6 | {
7 | "name": "abi_hash",
8 | "base": "",
9 | "fields": [
10 | {
11 | "name": "owner",
12 | "type": "name"
13 | },
14 | {
15 | "name": "hash",
16 | "type": "checksum256"
17 | }
18 | ]
19 | },
20 | {
21 | "name": "activate",
22 | "base": "",
23 | "fields": [
24 | {
25 | "name": "feature_digest",
26 | "type": "checksum256"
27 | }
28 | ]
29 | },
30 | {
31 | "name": "authority",
32 | "base": "",
33 | "fields": [
34 | {
35 | "name": "threshold",
36 | "type": "uint32"
37 | },
38 | {
39 | "name": "keys",
40 | "type": "key_weight[]"
41 | },
42 | {
43 | "name": "accounts",
44 | "type": "permission_level_weight[]"
45 | },
46 | {
47 | "name": "waits",
48 | "type": "wait_weight[]"
49 | }
50 | ]
51 | },
52 | {
53 | "name": "blockchain_parameters",
54 | "base": "",
55 | "fields": [
56 | {
57 | "name": "max_block_net_usage",
58 | "type": "uint64"
59 | },
60 | {
61 | "name": "target_block_net_usage_pct",
62 | "type": "uint32"
63 | },
64 | {
65 | "name": "max_transaction_net_usage",
66 | "type": "uint32"
67 | },
68 | {
69 | "name": "base_per_transaction_net_usage",
70 | "type": "uint32"
71 | },
72 | {
73 | "name": "net_usage_leeway",
74 | "type": "uint32"
75 | },
76 | {
77 | "name": "context_free_discount_net_usage_num",
78 | "type": "uint32"
79 | },
80 | {
81 | "name": "context_free_discount_net_usage_den",
82 | "type": "uint32"
83 | },
84 | {
85 | "name": "max_block_cpu_usage",
86 | "type": "uint32"
87 | },
88 | {
89 | "name": "target_block_cpu_usage_pct",
90 | "type": "uint32"
91 | },
92 | {
93 | "name": "max_transaction_cpu_usage",
94 | "type": "uint32"
95 | },
96 | {
97 | "name": "min_transaction_cpu_usage",
98 | "type": "uint32"
99 | },
100 | {
101 | "name": "max_transaction_lifetime",
102 | "type": "uint32"
103 | },
104 | {
105 | "name": "deferred_trx_expiration_window",
106 | "type": "uint32"
107 | },
108 | {
109 | "name": "max_transaction_delay",
110 | "type": "uint32"
111 | },
112 | {
113 | "name": "max_inline_action_size",
114 | "type": "uint32"
115 | },
116 | {
117 | "name": "max_inline_action_depth",
118 | "type": "uint16"
119 | },
120 | {
121 | "name": "max_authority_depth",
122 | "type": "uint16"
123 | }
124 | ]
125 | },
126 | {
127 | "name": "canceldelay",
128 | "base": "",
129 | "fields": [
130 | {
131 | "name": "canceling_auth",
132 | "type": "permission_level"
133 | },
134 | {
135 | "name": "trx_id",
136 | "type": "checksum256"
137 | }
138 | ]
139 | },
140 | {
141 | "name": "deleteauth",
142 | "base": "",
143 | "fields": [
144 | {
145 | "name": "account",
146 | "type": "name"
147 | },
148 | {
149 | "name": "permission",
150 | "type": "name"
151 | }
152 | ]
153 | },
154 | {
155 | "name": "key_weight",
156 | "base": "",
157 | "fields": [
158 | {
159 | "name": "key",
160 | "type": "public_key"
161 | },
162 | {
163 | "name": "weight",
164 | "type": "uint16"
165 | }
166 | ]
167 | },
168 | {
169 | "name": "linkauth",
170 | "base": "",
171 | "fields": [
172 | {
173 | "name": "account",
174 | "type": "name"
175 | },
176 | {
177 | "name": "code",
178 | "type": "name"
179 | },
180 | {
181 | "name": "type",
182 | "type": "name"
183 | },
184 | {
185 | "name": "requirement",
186 | "type": "name"
187 | }
188 | ]
189 | },
190 | {
191 | "name": "newaccount",
192 | "base": "",
193 | "fields": [
194 | {
195 | "name": "creator",
196 | "type": "name"
197 | },
198 | {
199 | "name": "name",
200 | "type": "name"
201 | },
202 | {
203 | "name": "owner",
204 | "type": "authority"
205 | },
206 | {
207 | "name": "active",
208 | "type": "authority"
209 | }
210 | ]
211 | },
212 | {
213 | "name": "onerror",
214 | "base": "",
215 | "fields": [
216 | {
217 | "name": "sender_id",
218 | "type": "uint128"
219 | },
220 | {
221 | "name": "sent_trx",
222 | "type": "bytes"
223 | }
224 | ]
225 | },
226 | {
227 | "name": "permission_level",
228 | "base": "",
229 | "fields": [
230 | {
231 | "name": "actor",
232 | "type": "name"
233 | },
234 | {
235 | "name": "permission",
236 | "type": "name"
237 | }
238 | ]
239 | },
240 | {
241 | "name": "permission_level_weight",
242 | "base": "",
243 | "fields": [
244 | {
245 | "name": "permission",
246 | "type": "permission_level"
247 | },
248 | {
249 | "name": "weight",
250 | "type": "uint16"
251 | }
252 | ]
253 | },
254 | {
255 | "name": "producer_key",
256 | "base": "",
257 | "fields": [
258 | {
259 | "name": "producer_name",
260 | "type": "name"
261 | },
262 | {
263 | "name": "block_signing_key",
264 | "type": "public_key"
265 | }
266 | ]
267 | },
268 | {
269 | "name": "reqactivated",
270 | "base": "",
271 | "fields": [
272 | {
273 | "name": "feature_digest",
274 | "type": "checksum256"
275 | }
276 | ]
277 | },
278 | {
279 | "name": "reqauth",
280 | "base": "",
281 | "fields": [
282 | {
283 | "name": "from",
284 | "type": "name"
285 | }
286 | ]
287 | },
288 | {
289 | "name": "setabi",
290 | "base": "",
291 | "fields": [
292 | {
293 | "name": "account",
294 | "type": "name"
295 | },
296 | {
297 | "name": "abi",
298 | "type": "bytes"
299 | }
300 | ]
301 | },
302 | {
303 | "name": "setalimits",
304 | "base": "",
305 | "fields": [
306 | {
307 | "name": "account",
308 | "type": "name"
309 | },
310 | {
311 | "name": "ram_bytes",
312 | "type": "int64"
313 | },
314 | {
315 | "name": "net_weight",
316 | "type": "int64"
317 | },
318 | {
319 | "name": "cpu_weight",
320 | "type": "int64"
321 | }
322 | ]
323 | },
324 | {
325 | "name": "setcode",
326 | "base": "",
327 | "fields": [
328 | {
329 | "name": "account",
330 | "type": "name"
331 | },
332 | {
333 | "name": "vmtype",
334 | "type": "uint8"
335 | },
336 | {
337 | "name": "vmversion",
338 | "type": "uint8"
339 | },
340 | {
341 | "name": "code",
342 | "type": "bytes"
343 | }
344 | ]
345 | },
346 | {
347 | "name": "setparams",
348 | "base": "",
349 | "fields": [
350 | {
351 | "name": "params",
352 | "type": "blockchain_parameters"
353 | }
354 | ]
355 | },
356 | {
357 | "name": "setpriv",
358 | "base": "",
359 | "fields": [
360 | {
361 | "name": "account",
362 | "type": "name"
363 | },
364 | {
365 | "name": "is_priv",
366 | "type": "uint8"
367 | }
368 | ]
369 | },
370 | {
371 | "name": "setprods",
372 | "base": "",
373 | "fields": [
374 | {
375 | "name": "schedule",
376 | "type": "producer_key[]"
377 | }
378 | ]
379 | },
380 | {
381 | "name": "unlinkauth",
382 | "base": "",
383 | "fields": [
384 | {
385 | "name": "account",
386 | "type": "name"
387 | },
388 | {
389 | "name": "code",
390 | "type": "name"
391 | },
392 | {
393 | "name": "type",
394 | "type": "name"
395 | }
396 | ]
397 | },
398 | {
399 | "name": "updateauth",
400 | "base": "",
401 | "fields": [
402 | {
403 | "name": "account",
404 | "type": "name"
405 | },
406 | {
407 | "name": "permission",
408 | "type": "name"
409 | },
410 | {
411 | "name": "parent",
412 | "type": "name"
413 | },
414 | {
415 | "name": "auth",
416 | "type": "authority"
417 | }
418 | ]
419 | },
420 | {
421 | "name": "wait_weight",
422 | "base": "",
423 | "fields": [
424 | {
425 | "name": "wait_sec",
426 | "type": "uint32"
427 | },
428 | {
429 | "name": "weight",
430 | "type": "uint16"
431 | }
432 | ]
433 | }
434 | ],
435 | "actions": [
436 | {
437 | "name": "activate",
438 | "type": "activate",
439 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Activate Protocol Feature\nsummary: 'Activate protocol feature {{nowrap feature_digest}}'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/admin.png#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e\n---\n\n{{$action.account}} activates the protocol feature with a digest of {{feature_digest}}."
440 | },
441 | {
442 | "name": "canceldelay",
443 | "type": "canceldelay",
444 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Cancel Delayed Transaction\nsummary: '{{nowrap canceling_auth.actor}} cancels a delayed transaction'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f\n---\n\n{{canceling_auth.actor}} cancels the delayed transaction with id {{trx_id}}."
445 | },
446 | {
447 | "name": "deleteauth",
448 | "type": "deleteauth",
449 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Delete Account Permission\nsummary: 'Delete the {{nowrap permission}} permission of {{nowrap account}}'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f\n---\n\nDelete the {{permission}} permission of {{account}}."
450 | },
451 | {
452 | "name": "linkauth",
453 | "type": "linkauth",
454 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Link Action to Permission\nsummary: '{{nowrap account}} sets the minimum required permission for the {{#if type}}{{nowrap type}} action of the{{/if}} {{nowrap code}} contract to {{nowrap requirement}}'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f\n---\n\n{{account}} sets the minimum required permission for the {{#if type}}{{type}} action of the{{/if}} {{code}} contract to {{requirement}}.\n\n{{#if type}}{{else}}Any links explicitly associated to specific actions of {{code}} will take precedence.{{/if}}"
455 | },
456 | {
457 | "name": "newaccount",
458 | "type": "newaccount",
459 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Create New Account\nsummary: '{{nowrap creator}} creates a new account with the name {{nowrap name}}'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f\n---\n\n{{creator}} creates a new account with the name {{name}} and the following permissions:\n\nowner permission with authority:\n{{to_json owner}}\n\nactive permission with authority:\n{{to_json active}}"
460 | },
461 | {
462 | "name": "onerror",
463 | "type": "onerror",
464 | "ricardian_contract": ""
465 | },
466 | {
467 | "name": "reqactivated",
468 | "type": "reqactivated",
469 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Assert Protocol Feature Activation\nsummary: 'Assert that protocol feature {{nowrap feature_digest}} has been activated'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/admin.png#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e\n---\n\nAssert that the protocol feature with a digest of {{feature_digest}} has been activated."
470 | },
471 | {
472 | "name": "reqauth",
473 | "type": "reqauth",
474 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Assert Authorization\nsummary: 'Assert that authorization by {{nowrap from}} is provided'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f\n---\n\nAssert that authorization by {{from}} is provided."
475 | },
476 | {
477 | "name": "setabi",
478 | "type": "setabi",
479 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Deploy Contract ABI\nsummary: 'Deploy contract ABI on account {{nowrap account}}'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f\n---\n\nDeploy the ABI file associated with the contract on account {{account}}."
480 | },
481 | {
482 | "name": "setalimits",
483 | "type": "setalimits",
484 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Adjust Resource Limits of Account\nsummary: 'Adjust resource limits of account {{nowrap account}}'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/admin.png#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e\n---\n\n{{$action.account}} updates {{account}}’s resource limits to have a RAM quota of {{ram_bytes}} bytes, a NET bandwidth quota of {{net_weight}} and a CPU bandwidth quota of {{cpu_weight}}."
485 | },
486 | {
487 | "name": "setcode",
488 | "type": "setcode",
489 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Deploy Contract Code\nsummary: 'Deploy contract code on account {{nowrap account}}'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f\n---\n\nDeploy compiled contract code to the account {{account}}."
490 | },
491 | {
492 | "name": "setparams",
493 | "type": "setparams",
494 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Set System Parameters\nsummary: 'Set system parameters'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/admin.png#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e\n---\n\n{{$action.account}} sets system parameters to:\n{{to_json params}}"
495 | },
496 | {
497 | "name": "setpriv",
498 | "type": "setpriv",
499 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Make an Account Privileged or Unprivileged\nsummary: '{{#if is_priv}}Make {{nowrap account}} privileged{{else}}Remove privileged status of {{nowrap account}}{{/if}}'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/admin.png#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e\n---\n\n{{#if is_priv}}\n{{$action.account}} makes {{account}} privileged.\n{{else}}\n{{$action.account}} removes privileged status of {{account}}.\n{{/if}}"
500 | },
501 | {
502 | "name": "setprods",
503 | "type": "setprods",
504 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Set Block Producers\nsummary: 'Set block producer schedule'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/admin.png#9bf1cec664863bd6aaac0f814b235f8799fb02c850e9aa5da34e8a004bd6518e\n---\n\n{{$action.account}} proposes a block producer schedule of:\n{{#each schedule}}\n 1. {{this.producer_name}} with a block signing key of {{this.block_signing_key}}\n{{/each}}"
505 | },
506 | {
507 | "name": "unlinkauth",
508 | "type": "unlinkauth",
509 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Unlink Action from Permission\nsummary: '{{nowrap account}} unsets the minimum required permission for the {{#if type}}{{nowrap type}} action of the{{/if}} {{nowrap code}} contract'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f\n---\n\n{{account}} removes the association between the {{#if type}}{{type}} action of the{{/if}} {{code}} contract and its minimum required permission.\n\n{{#if type}}{{else}}This will not remove any links explicitly associated to specific actions of {{code}}.{{/if}}"
510 | },
511 | {
512 | "name": "updateauth",
513 | "type": "updateauth",
514 | "ricardian_contract": "---\nspec_version: \"0.2.0\"\ntitle: Modify Account Permission\nsummary: 'Add or update the {{nowrap permission}} permission of {{nowrap account}}'\nicon: http://127.0.0.1/ricardian_assets/eosio.contracts/icons/account.png#3d55a2fc3a5c20b456f5657faf666bc25ffd06f4836c5e8256f741149b0b294f\n---\n\nModify, and create if necessary, the {{permission}} permission of {{account}} to have a parent permission of {{parent}} and the following authority:\n{{to_json auth}}"
515 | }
516 | ],
517 | "tables": [
518 | {
519 | "name": "abihash",
520 | "type": "abi_hash",
521 | "index_type": "i64",
522 | "key_names": [],
523 | "key_types": []
524 | }
525 | ],
526 | "ricardian_clauses": [],
527 | "variants": []
528 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🌴 Tropical Example
2 | Tropical Example is a mock application for renting properties. It will be referenced throughout this guide as an example for application developers to start building secure applications with a good user experience on the EOSIO blockchain.
3 |
4 | 
5 |
6 | ## About EOSIO Labs
7 |
8 | EOSIO Labs repositories are experimental. Developers in the community are encouraged to use EOSIO Labs repositories as the basis for code and concepts to incorporate into their applications. Community members are also welcome to contribute and further develop these repositories. Since these repositories are not supported by Block.one, we may not provide responses to issue reports, pull requests, updates to functionality, or other requests from the community, and we encourage the community to take responsibility for these.
9 |
10 | ## Overview
11 |
12 | ### Try it out in Gitpod ###
13 |
14 | Gitpod [launches the app](https://gitpod.io/#https://github.com/EOSIO/tropical-example-web-app) for you. It starts the required blockchain in the background, launches the web server, and opens a preview window.
15 | NOTES:
16 | 1) There are several times during startup it might look like startup hangs, namely... near the end of the docker build, once the IDE comes up, and then once the preview shows.
17 | 2) Sometimes when Gitpod launches the webapp preview, it does so prematurely. Just click the small refresh circular arrow icon in the top left of the preview window.
18 | 3) Gitpod generates a dynamic URL for the browser to access the app from. This URL is needed in numerous parts of the app, so note that there is code in this repo specifically meant for Gitpod compatibility. A comment has been added in those locations to point it out.
19 | 4) To use Scatter in Gitpod, launch the demo in Gitpod, then go into Scatter's Networks section and add a custom network with the following settings as well as adding the account name. Note that these settings will need to be updated each time you launch the demo in Gitpod (because the URL will be different each time).
20 | * Network Settings
21 | * **Host**:
22 | * **Protocol**: https
23 | * **Port**: 443
24 | * **Chain ID**: cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f (This is the test chainId used in the example)
25 | 
26 | * Adding account name
27 | * After you've imported the private key from this example (see other parts of the README for those instructions), Scatter might not pull the "example" account from the network. If that's the case, in the Wallet section, if "example" doesn't show up under your imported key with a balance to the right, on a Mac, you'll hold Ctrl when you click the three horizontal dot button to the right of your imported key. Ctrl will enable a normally-hidden item called "Link Account". Click that and in the first box, type "example" and in the drop-down, select the custom network you created above. See screenshot below for what this looks like.
28 | 
29 | Read more about [Gitpod workspaces here](https://gitpod.io)
30 |
31 | The following open source repositories are utilized in Tropical Example:
32 |
33 | * Using the [Universal Authenticator Library (UAL)](https://github.com/EOSIO/universal-authenticator-library/) for quick and easy integration with multiple authentication providers (wallets).
34 | * Increasing the security and transparency of your application by following the [Manifest Specification](https://github.com/EOSIO/manifest-spec).
35 | * Displaying human readable Ricardian Contracts of your proposed EOSIO actions by following the [Ricardian Specification](https://github.com/EOSIO/ricardian-spec).
36 |
37 | ## Table of Contents
38 | - [Universal Authenticator Library (UAL)](#universal-authenticator-library-ual)
39 | - [Installation](#installation)
40 | - [Setup](#setup)
41 | - [UAL Context](#ual-context)
42 | - [Login](#login)
43 | - [Modal](#modal)
44 | - [Account Name](#account-name)
45 | - [Transactions](#transactions)
46 | - [Logout](#logout)
47 | - [Errors](#errors)
48 | - [Login Errors](#login-errors)
49 | - [Transactions Errors](#transactions-errors)
50 | - [Manifest Specification](#manifest-specification)
51 | - [Ricardian Specification](#ricardian-specification)
52 | - [WebAuthn](#webauthn)
53 | - [Running Tropical Example](#running-tropical-example)
54 | - [Required Tools](#required-tools)
55 | - [Setup](#setup-1)
56 | - [.env file defaults](#env-file-defaults)
57 | - [Installation](#installation-1)
58 | - [Running Nodeos](#running-nodeos)
59 | - [Running Frontend](#running-frontend)
60 | - [Login](#login-1)
61 | - [Using WebAuthn](#using-webauthn)
62 | - [Other Available Actions](#other-available-actions)
63 | - [Docker Compose Command Reference](#docker-compose-command-reference)
64 | - [Links](#links)
65 | - [Contributing](#contributing)
66 | - [License](#license)
67 | - [Important](#important)
68 |
69 | ## Universal Authenticator Library (UAL)
70 |
71 | An Authenticator provides the ability to communicate with an authentication provider. Authentication providers generally allow users to add, modify, and delete private / public key pairs and use these key pairs to sign proposed transactions.
72 |
73 | UAL allows developers to support multiple Authenticators with only a few lines of code. This significantly reduces the start up time of creating applications by removing the need to detect and create an interface for interacting with the Authenticators.
74 |
75 | UAL provides users with a common login interface in which they can select the Authenticator of their choice to interact with the EOSIO protocol. Once a user selects the Authenticator of their choice and logs in, the application developer will have access to an `activeUser` object which contains all necessary fields and functions to sign transactions and customize their user experience.
76 |
77 | ### Installation
78 |
79 | First install your [UAL Renderer](https://github.com/EOSIO/universal-authenticator-library#usage-dapp-developer) of choice. Tropical Example uses the [UAL Renderer for ReactJS](https://github.com/EOSIO/ual-reactjs-renderer) and the rest of the examples will be demonstrating usage with the React Renderer. Please view the [UAL documentation](https://github.com/EOSIO/universal-authenticator-library#usage-dapp-developer) for links to all available renderers with documentation and examples of their usage.
80 |
81 | ```bash
82 | yarn add ual-reactjs-renderer
83 | ```
84 |
85 | Then install the Authenticators you want to allow users to interact with. Tropical Example uses the following Authenticators:
86 | - [UAL for EOSIO Reference Authenticator](https://github.com/EOSIO/ual-eosio-reference-authenticator)
87 | - [UAL for Scatter](https://github.com/EOSIO/ual-scatter)
88 | - [UAL for Lynx](https://github.com/EOSIO/ual-lynx)
89 | - [UAL for Token Pocket](https://github.com/EOSIO/ual-token-pocket)
90 |
91 | ```bash
92 | yarn add ual-eosio-reference-authenticator
93 | yarn add ual-scatter
94 | yarn add ual-lynx
95 | yarn add ual-token-pocket
96 | ```
97 |
98 | ### Setup
99 |
100 | In your root React component (for most projects this will be index.js) wrap your App component with `UALProvider`.
101 |
102 | The `UALProvider` requires an array of Chains you wish your app to transact on, an array of Authenticators you want to allow users to interact with, and an application name. Each Authenticator requires at least an array of Chains that you want to allow the Authenticator to interact with and a second options parameter that may be required. Please see the documentation of the Authenticator if this options argument is required and what fields are necessary.
103 |
104 | ```javascript
105 | // UAL Required Imports
106 | import { UALProvider } from 'ual-reactjs-renderer'
107 | // Authenticator Imports
108 | import { EOSIOAuth } from 'ual-eosio-reference-authenticator'
109 | import { Scatter } from 'ual-scatter'
110 | import { Lynx } from 'ual-lynx'
111 | import { TokenPocket } from 'ual-token-pocket'
112 | ...
113 | const appName = 'Tropical-Example'
114 |
115 | // Chains
116 | const chain = {
117 | chainId: process.env.REACT_APP_CHAIN_ID,
118 | rpcEndpoints: [
119 | {
120 | protocol: process.env.REACT_APP_RPC_PROTOCOL,
121 | host: process.env.REACT_APP_RPC_HOST,
122 | port: process.env.REACT_APP_RPC_PORT,
123 | },
124 | ],
125 | }
126 |
127 | // Authenticators
128 | const eosioAuth = new EOSIOAuth([chain], { appName, protocol: 'eosio' })
129 | const scatter = new Scatter([chain], { appName })
130 | const lynx = new Lynx([chain])
131 | const tokenPocket = new TokenPocket([chain])
132 |
133 | const supportedChains = [chain]
134 | const supportedAuthenticators = [eosioAuth, scatter, lynx, tokenPocket]
135 |
136 | ReactDOM.render(
137 |
138 |
139 | ,
140 | document.getElementById('root'),
141 | )
142 | ```
143 |
144 | ### UAL Context
145 |
146 | The UAL Renderer for ReactJS uses [Context](https://reactjs.org/docs/context.html) to expose the objects and functions needed to interact with UAL. The context is created by the `UALProvider`. There are two methods to gain access to this context:
147 |
148 | 1) The `withUAL` [HOC (Higher Order Component)](https://reactjs.org/docs/higher-order-components.html) can be used to pass the `UALProvider` context as props to the wrapped component.
149 |
150 | * **When using the `withUAL` HOC all of the `UALProvider` context will be available under the parent prop `ual`**
151 |
152 | ```javascript
153 | import { withUAL } from 'ual-reactjs-renderer'
154 | class Example extends React.Component {
155 | render() {
156 | const { ual: { logout } } = this.props
157 | return
Logout
158 | }
159 | }
160 |
161 | export default withUAL(Example)
162 | ```
163 |
164 | 2) The `static contextType` property can be set on a class to the renderer's exported context object, `UALContext`. This allows the context to be referenced using `this.context` within the class.
165 |
166 | * **Using the static `contextType` to access the context is currently only supported by React component classes and not supported by functional components. For functional components, `withUAL` must be used if access to the context is required.**
167 |
168 | ```javascript
169 | import { UALContext } from 'ual-reactjs-renderer'
170 | class Example extends React.Component {
171 | static contextType = UALContext
172 |
173 | render() {
174 | const { logout } = this.context
175 | return
Logout
176 | }
177 | }
178 | ```
179 |
180 | ### Login
181 |
182 | #### Modal
183 |
184 | By default, the `UALProvider` provides a modal at the root level of your application. This modal will render the login buttons of all the configured Authenticators that can be detected in the user’s environment. The modal is hidden by default, but can be displayed and dismissed by calling the functions `showModal` and `hideModal`, respectively. Both functions are set in the `UALProvider` context.
185 |
186 | ```javascript
187 | import { withUAL } from 'ual-reactjs-renderer'
188 | class App extends React.Component {
189 | ...
190 | displayLoginModal = (display) => {
191 | const { ual: { showModal, hideModal } } = this.props
192 | if (display) {
193 | showModal()
194 | } else {
195 | hideModal()
196 | }
197 | }
198 | ...
199 | }
200 |
201 | export default withUAL(App)
202 | ```
203 |
204 | #### Account Name
205 |
206 | After logging in, an `activeUser` object is returned by the Authenticator and set in the `UALProvider` context.
207 |
208 | On the `activeUser` object a `getAccountName` method is available. This method returns a promise, which will resolve to a string containing the signed in account name.
209 |
210 | ```javascript
211 | import { UALContext } from 'ual-reactjs-renderer'
212 | class UserInfo extends React.Component {
213 | static contextType = UALContext
214 | ...
215 | async componentDidMount() {
216 | const { activeUser } = this.context
217 | if (activeUser) {
218 | const accountName = await activeUser.getAccountName()
219 | this.setState({ accountName })
220 | }
221 | }
222 | ...
223 | }
224 | ```
225 |
226 | ### Transactions
227 |
228 | In order to propose transactions, your application needs access to the `activeUser` object returned by the logged in Authenticator.
229 |
230 | At the time of signing, call `activeUser.signTransaction` with a valid transaction object and a [configuration object](https://github.com/EOSIO/universal-authenticator-library/blob/master/src/interfaces.ts#L40). This will propose the transaction to the logged in Authenticator.
231 |
232 | It is **highly recommended** in the transaction configuration to provide a `expireSeconds` property of a time greater than at least `300` seconds or 5 minutes. This will allow sufficient time for users to review and accept their transactions before expiration.
233 |
234 | ```javascript
235 | import { UALContext } from 'ual-reactjs-renderer'
236 | import { generateLikeTransaction } from 'utils/transaction'
237 | ...
238 | class Property extends React.Component {
239 | static contextType = UALContext
240 | ...
241 | onLike = async () => {
242 | const { login, displayError } = this.props
243 | // Via static contextType = UALContext, access to the activeUser object on this.context is now available
244 | const { activeUser } = this.context
245 | if (activeUser) {
246 | try {
247 | const accountName = await activeUser.getAccountName()
248 | const transaction = generateLikeTransaction(accountName)
249 | // The activeUser.signTransaction will propose the passed in transaction to the logged in Authenticator
250 | await activeUser.signTransaction(transaction, { broadcast: true, expireSeconds: 300 })
251 | this.setState({ liked: true })
252 | } catch (err) {
253 | displayError(err)
254 | }
255 | } else {
256 | login()
257 | }
258 | }
259 | ...
260 | }
261 |
262 | export default Property
263 | ```
264 |
265 | The method `activeUser.signTransaction` returns a promise, which, if signing is successful, will resolve to the [signed transaction response](https://github.com/EOSIO/universal-authenticator-library/blob/master/src/interfaces.ts#L52).
266 |
267 | ### Logout
268 |
269 | If you want to logout, you can use the logout function set in the `UALProvider` context.
270 |
271 | ```javascript
272 | import { UALContext } from 'ual-reactjs-renderer'
273 | class UserInfo extends React.Component {
274 | static contextType = UALContext
275 | ...
276 | renderDropdown = () => {
277 | const { logout } = this.context
278 | return (
279 |
280 |
281 |
282 | )
283 | }
284 | ...
285 | }
286 |
287 | export default UserInfo
288 | ```
289 |
290 | ### Errors
291 |
292 | Errors thrown by UAL are of type [`UALError`](https://github.com/EOSIO/universal-authenticator-library/blob/master/src/UALError.ts), which extends the generic `Error` class, but has extra information that is useful for debugging purposes.
293 |
294 | #### Login Errors
295 |
296 | During login, errors are set in the `UALProvider` context.
297 |
298 | ```javascript
299 | // Using withUAL() HOC
300 | this.props.ual.error
301 | ```
302 |
303 | ```javascript
304 | // Using static contextType
305 | this.context.error
306 | ```
307 |
308 | #### Transactions Errors
309 |
310 | During signing, errors will be thrown by `activeUser.signTransaction`. It is recommended to use the `try...catch` statement to capture these thrown errors.
311 |
312 | ```javascript
313 | try {
314 | await activeUser.signTransaction(transaction, transactionConfig)
315 | } catch (error) {
316 | // Using JSON.parse(JSON.stringify(error)) creates a copy of the error object to ensure
317 | // that you are printing the value of object at the moment you log it
318 | console.error('UAL Error', JSON.parse(JSON.stringify(error)))
319 | }
320 | ```
321 |
322 | _If you need information not covered in this guide, you can reference the full UAL repository [here](https://github.com/EOSIO/universal-authenticator-library)._
323 |
324 | ## Manifest Specification
325 |
326 | Tropical Example follows the Manifest Specification by providing the following:
327 |
328 | * A publicly accessible [app-metadata.json](https://github.com/EOSIO/tropical-example-web-app/blob/master/public/app-metadata.json).
329 | * A publicly accessible [chain-manifests.json](https://github.com/EOSIO/tropical-example-web-app/blob/master/public/chain-manifests.json)
330 | * Registering the app's Manifest on the local chain [via cleos](https://github.com/EOSIO/tropical-example-web-app/blob/master/eosio/scripts/deploy_contracts.sh#L114)
331 |
332 | _If you need information not covered in this guide, you can reference the Manifest Specification [here](https://github.com/EOSIO/manifest-spec)._
333 |
334 | ## Ricardian Specification
335 |
336 | Tropical Example follows the Ricardian Specification by providing the following:
337 |
338 | * A [tropical.contracts.md](https://github.com/EOSIO/tropical-example-web-app/blob/master/eosio/contracts/tropical/tropical.contracts.md), which defines the Ricardian Contract of the `like` action of the `tropical` contract.
339 | * Generating the `tropical` abi file with [eosio-cpp](https://github.com/EOSIO/tropical-example-web-app/blob/master/eosio/scripts/deploy_contracts.sh#L80) by passing the `-abigen` flag, which will auto generate an abi including the `tropical.contracts.md` into the `ricardian_contract` field of the `like` action.
340 |
341 | _If you need information not covered in this guide, you can reference the Ricardian Specification [here](https://github.com/EOSIO/ricardian-spec)._
342 |
343 | ## WebAuthn
344 |
345 | Tropical Example implements WebAuthn as a 2nd factor.
346 |
347 | After logging in, under the user menu, you'll find an option to "enroll" a 2FA device. Use this option in conjunction with your device's build-in biometric scanner, secure element, or external hardware key to enroll a key with the Tropical Example.
348 |
349 | Then, on the Properties Search Results page, you'll see a 'Rent' button. Where liking something is a relatively low-risk activity, the Rent button represents a real-world use case for commiting yourself to rent that property. In this case where money is on the line, the app will request you sign for the Rent action with the enrolled key.
350 |
351 | Read more about this example and technology [here -- REQUIRE LINK to blog or Release Notes of some kind](https://www.google.com)
352 |
353 | ## Running Tropical Example
354 |
355 | ### Required Tools
356 |
357 | * [Yarn](https://yarnpkg.com/lang/en/) with support at `^1.15.2` (latest stable).
358 | * [Docker](https://www.docker.com/) with support at Docker Engine `18.09.2` (latest stable).
359 | * [Docker Compose](https://docs.docker.com/compose/).
360 | * Mac and Windows environments - By default the Docker Compose tool is installed with Docker.
361 | * Linux - Follow [these instructions to install Docker Compose](https://docs.docker.com/compose/install/).
362 | * [Node.js](https://nodejs.org/en/) with support at `^10.15.3` LTS. **NOTICE** This project will not build on the current version of Node.js `12.3.1` due to an error in a sub-dependency of `react-scripts`.
363 |
364 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
365 |
366 | ### Setup
367 |
368 | Create a `.env` file from the `default.env`
369 | ```bash
370 | cp default.env .env
371 | ```
372 |
373 | Tropical Example uses an environment configuration for the Chain and RPC endpoints. By default it will query the local node setup by Docker Compose in this repo. If you want to use another Chain, update the values in the .env file you created in the first step to set the preferred Chain you wish your app to transact on.
374 |
375 | #### .env file defaults
376 |
377 | ```
378 | REACT_APP_CHAIN_ID=cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f
379 | REACT_APP_RPC_PROTOCOL=http
380 | REACT_APP_RPC_HOST=localhost
381 | REACT_APP_RPC_PORT=8888
382 | ```
383 |
384 | ### Installation
385 |
386 | ```bash
387 | yarn
388 | ```
389 | Run this first to install all the project's dependencies.
390 |
391 | ### Running Nodeos
392 |
393 | Before the app can be run, the Tropical Example contract must be deployed on the chain configured in the `.env` to the account `tropical`.
394 |
395 | This repo provides a `docker-compose.yml` that will setup and deploy the `tropical` contract using Docker Compose.
396 |
397 | Then run the following to start up a local node:
398 | ```bash
399 | yarn up
400 | ```
401 |
402 | You can view the contract in the [eosio/contracts directory](https://github.com/EOSIO/tropical-example-web-app/tree/master/eosio/contracts/tropical).
403 |
404 | ### Running Frontend
405 |
406 | ```bash
407 | yarn start
408 | ```
409 | This command runs the app in development mode over SSL. You will need to install a self-signed SSL certificate or enable [allow-insecure-localhost](chrome://flags/#allow-insecure-localhost) if running over SSL in chrome.
410 | Open [https://localhost:3000](https://localhost:3000) to view it in the browser.
411 |
412 | The page will reload if you make edits.
413 |
414 | ### Login
415 |
416 | The Docker Compose setup scripts provide an, `example` account, that can be imported into your Authenticator of choice to login and sign transactions:
417 |
418 | ⚠️ ***Never use this development key for a production account! Doing so will most certainly result in the loss of access to your account, this private key is publicly known.*** ⚠️
419 | ```bash
420 | # Example Account Public Key
421 | EOS6TWM95TUqpgcjYnvXSK5kBsi6LryWRxmcBaULVTvf5zxkaMYWf
422 | # Example Account Private Key
423 | 5KkXYBUb7oXrq9cvEYT3HXsoHvaC2957VKVftVRuCy7Z7LyUcQB
424 | ```
425 |
426 | ### Using WebAuthn
427 |
428 | After setting up the application and logging in, you can enable WebAuthn if you want to be able to `rent` a property.
429 | 
430 |
431 | Once you enable WebAuthn with your choice of hardware, you can browse to the list of properties and select `rent`. Scatter will prompt you to allow this action by authenticating with your hardware.
432 | 
433 |
434 | After confirming the transaction, you should now see an indicator that your property has been rented successfully.
435 | 
436 |
437 | #### Other Available Actions
438 |
439 | You can like a property (WebAuthn not required). After browsing to the list of properties and selecting `like`, scatter will prompt you to allow this action.
440 | 
441 |
442 | After confirming the transaction, you should now see an indicator that your property has been liked successfully.
443 | 
444 |
445 | ### Docker Compose Command Reference
446 |
447 | ```bash
448 | # Create and start the docker container
449 | docker-compose up eosio
450 | # Stop the docker container
451 | docker-compose down eosio
452 | # Open a bash terminal into the docker container
453 | docker-compose exec eosio /bin/bash
454 | ```
455 |
456 | ## Links
457 | - [Universal Authenticator Library (UAL)](https://github.com/EOSIO/universal-authenticator-library)
458 | - [Manifest Specification](https://github.com/EOSIO/manifest-spec)
459 | - [Ricardian Specification](https://github.com/EOSIO/ricardian-spec)
460 | - [Docker Compose CLI Reference](https://docs.docker.com/compose/reference/)
461 |
462 | ## Contributing
463 | Check out the [Contributing](./CONTRIBUTING.md) guide and please adhere to the [Code of Conduct](./CONTRIBUTING.md#conduct)
464 |
465 | ## License
466 | [MIT licensed](./LICENSE)
467 |
468 | ## Important
469 |
470 | See [LICENSE](./LICENSE) for copyright and license terms.
471 |
472 | All repositories and other materials are provided subject to the terms of this [IMPORTANT](./IMPORTANT.md) notice and you must familiarize yourself with its terms. The notice contains important information, limitations and restrictions relating to our software, publications, trademarks, third-party resources, and forward-looking statements. By accessing any of our repositories and other materials, you accept and agree to the terms of the notice.
473 |
--------------------------------------------------------------------------------