mirror of
https://github.com/LaconicNetwork/laconic.com.git
synced 2026-01-13 23:24:07 +00:00
* Changes made to facilitate using local JSON files as a content source rather than dato cms Set follwoing variable in env to enable the changeover: NEXT_PUBLIC_DATOCMS_BYPASS_TYPE="local_json" Setting the above env variable to anything else will revert the site to pulling from datocms, assuming the account is still active with them. Look for any comment tagged with NEXT_PUBLIC_DATOCMS_BYPASS to see where the intercepts occur Signed-off-by: Traxus <shyidx@gmail.com> * update example ENV to include new variable for refrence Signed-off-by: Traxus <shyidx@gmail.com> * Fix Type error: 'getAllBlogPostsSlugs' is declared but its value is never read. Signed-off-by: Traxus <shyidx@gmail.com> * typescript test Signed-off-by: Traxus <shyidx@gmail.com> * primitive typescript appeasement vol 2 Signed-off-by: Traxus <shyidx@gmail.com> * ./src/lib/datocms-bypass.ts:72:6 Type error: Variable 'directories' implicitly has type 'any[]' in some locations where its type cannot be determined. Signed-off-by: Traxus <shyidx@gmail.com> * typescript appeasment vol 3 Signed-off-by: Traxus <shyidx@gmail.com> * typescript Signed-off-by: Traxus <shyidx@gmail.com> * typescript Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * lint Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * simple-import-sort, sorry. Signed-off-by: Traxus <shyidx@gmail.com> * Signed-off-by: Traxus <shyidx@gmail.com> * testing a blog post update * Trying to restore the lint command file Signed-off-by: Traxus <shyidx@gmail.com> * Remove Press Page Signed-off-by: Traxus <shyidx@gmail.com> * Hide Test Blog post Signed-off-by: Traxus <shyidx@gmail.com> * moved the copy of /press to /src/_old_pages/_press so that there would be a refrence copy but to keep the url inacessible to the public Signed-off-by: Traxus <shyidx@gmail.com> --------- Signed-off-by: Traxus <shyidx@gmail.com> Co-authored-by: Traxus <shyidx@gmail.com>
1544 lines
66 KiB
JSON
1544 lines
66 KiB
JSON
{
|
||
"data": {
|
||
"blogPost": {
|
||
"author": {
|
||
"id": "63992470",
|
||
"name": "Zach Ramsay"
|
||
},
|
||
"category": [
|
||
{
|
||
"slug": "developers",
|
||
"title": "Developers",
|
||
"id": "6311820"
|
||
},
|
||
{
|
||
"slug": "not-product",
|
||
"title": "Not Product",
|
||
"id": "3545003"
|
||
}
|
||
],
|
||
"content": {
|
||
"blocks": [],
|
||
"links": [],
|
||
"value": {
|
||
"schema": "dast",
|
||
"document": {
|
||
"type": "root",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "In "
|
||
},
|
||
{
|
||
"url": "https://www.laconic.com/blog/intro-to-the-laconic-stack",
|
||
"meta": [
|
||
{
|
||
"id": "rel",
|
||
"value": "noopener noreferrer"
|
||
},
|
||
{
|
||
"id": "target",
|
||
"value": "_blank"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "the last blog post"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": ", we introduced all the main components of the Laconic Stack. The first point of entry for any developer wishing to use Laconic is "
|
||
},
|
||
{
|
||
"url": "https://github.com/cerc-io/stack-orchestrator",
|
||
"meta": [
|
||
{
|
||
"id": "rel",
|
||
"value": "noopener noreferrer"
|
||
},
|
||
{
|
||
"id": "target",
|
||
"value": "_blank"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Stack Orchestrator"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": ". It allows you to stand up a local fixturenet for testing purposes. Integrated directly into Stack Orchestrator are several \"stacks\" which work out of the box. Today, we'll be going over the ERC20 \"stack\" to provide an overview of some key components of the Laconic Stack."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "You will accomplish the following:\n"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "list",
|
||
"style": "bulleted",
|
||
"children": [
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "stand up the core stack using Stack Orchestrator"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "deploy an ERC20 token"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "deploy an ERC20 Watcher"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "send tokens to and from your local account to a new account on Metamask"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "use GraphQL to query the watcher for information about the token and accounts"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "heading",
|
||
"level": 2,
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Install"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "This tutorial assumes you are on a local machine (Mac or Linux). Trying it in the cloud requires additional configurations (e.g., opening ports) not covered here."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "heading",
|
||
"level": 3,
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Pre-requisites"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "list",
|
||
"style": "bulleted",
|
||
"children": [
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "`"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "python3"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` "
|
||
},
|
||
{
|
||
"url": "https://www.python.org/downloads/",
|
||
"meta": [
|
||
{
|
||
"id": "rel",
|
||
"value": "nofollow"
|
||
},
|
||
{
|
||
"id": "target",
|
||
"value": "_blank"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Install"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "`"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "docker"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` "
|
||
},
|
||
{
|
||
"url": "https://docs.docker.com/get-docker/",
|
||
"meta": [
|
||
{
|
||
"id": "rel",
|
||
"value": "nofollow"
|
||
},
|
||
{
|
||
"id": "target",
|
||
"value": "_blank"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Install"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "`"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "docker-compose"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` "
|
||
},
|
||
{
|
||
"url": "https://docs.docker.com/compose/install/",
|
||
"meta": [
|
||
{
|
||
"id": "rel",
|
||
"value": "nofollow"
|
||
},
|
||
{
|
||
"id": "target",
|
||
"value": "_blank"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Install"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "MetaMask "
|
||
},
|
||
{
|
||
"url": "https://metamask.io/download/",
|
||
"meta": [
|
||
{
|
||
"id": "rel",
|
||
"value": "nofollow"
|
||
},
|
||
{
|
||
"id": "target",
|
||
"value": "_blank"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Install"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": " in the supported browser of your choice."
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "If using a fresh Ubuntu Digital Ocean droplet, check out "
|
||
},
|
||
{
|
||
"url": "https://github.com/LaconicNetwork/Laconic-Documentation/blob/staging/scripts/install-laconic-stack.sh",
|
||
"meta": [
|
||
{
|
||
"id": "target",
|
||
"value": "_blank"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "this script"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": " for a quick setup."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "WARNING"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": ": if installing docker-compose via package manager (as opposed to Docker Desktop), you must install the plugin, e.g., on Linux:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "mkdir -p ~/.docker/cli-plugins\ncurl -SL https://github.com/docker/compose/releases/download/v2.11.2/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose\nchmod +x ~/.docker/cli-plugins/docker-compose",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Next, install the latest release of Stack Orchestrator"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "curl -L -o laconic-so https://github.com/cerc-io/stack-orchestrator/releases/latest/download/laconic-so",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Give it permission:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "chmod +x laconic-so",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Verify operation:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "./laconic-so \nUsage: python -m laconic-so [OPTIONS] COMMAND [ARGS]...\n\n Laconic Stack Orchestrator\n\nOptions:\n --stack TEXT specify a stack to build/deploy\n --quiet\n --verbose\n --dry-run\n --local-stack\n --debug\n --continue-on-error\n -h, --help Show this message and exit.\n\nCommands:\n build-containers build the set of containers required for a complete...\n build-npms build the set of npm packages required for a...\n deploy-system deploy a stack\n setup-repositories git clone the set of repositories required to build...\n version print tool version",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "For a more permanent setup, move the binary to `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "~/bin"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` and add it your `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "PATH"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "`."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "heading",
|
||
"level": 2,
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Stack Orchestrator"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "The `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "laconic-so"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` CLI tool makes it easy to experiment with various components of the stack. It allows you to quickly and seamlessly experiment with watchers. Because it uses docker/docker-compose, several commands in this tutorial will leverage the ability to execute commands directly in the containers. This, for example, means that `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "yarn"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` doesn't need to be installed on your local machine."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "heading",
|
||
"level": 2,
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Setup"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Use the stack orchestrator to pull the core repositories:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "./laconic-so --stack erc20 setup-repositories",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "You'll see something like:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "Dev Root is: /root/cerc\nChecking: /root/cerc/go-ethereum: Needs to be fetched\n100%|####################################################################################################| 71.6k/71.6k [00:23<00:00, 3.10kB/s]\nChecking: /root/cerc/ipld-eth-db: Needs to be fetched\n100%|##########################################################################################################| 595/595 [00:00<00:00, 991B/s]\nChecking: /root/cerc/ipld-eth-server: Needs to be fetched\n100%|####################################################################################################| 25.5k/25.5k [00:06<00:00, 3.82kB/s]\nChecking: /root/cerc/watcher-ts: Needs to be fetched\n100%|####################################################################################################| 8.79k/8.79k [00:01<00:00, 4.49kB/s]",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Next, we'll build the docker images for each repo we just fetched."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "./laconic-so --stack erc20 build-containers ",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "This process will take 10-15 minutes, go make a pot of coffee. The output will give you an idea of what's going on. Eventually, you'll see:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "Successfully built 77c75d57ad66\nSuccessfully tagged cerc/watcher-erc20:local",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Next, let's deploy this stack:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "./laconic-so --stack erc20deploy-system up",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "The output will looks like this (ignore the warnings):"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "WARN[0000] The \"eth_proxy_on_error\" variable is not set. Defaulting to a blank string. \nWARN[0000] The \"eth_forward_eth_calls\" variable is not set. Defaulting to a blank string. \nWARN[0000] The \"eth_http_path\" variable is not set. Defaulting to a blank string. \n[+] Running 23/23\n ⠿ ipld-eth-db Pulled 18.4s\n ⠿ 213ec9aee27d Already exists 0.0s\n ⠿ 85c3ef7cf9a6 Pull complete 0.7s\n ⠿ ac29cc04759a Pull complete 0.9s\n ⠿ 2a37e244d86b Pull complete 13.5s\n ⠿ 36d7202aa1cf Pull complete 13.8s\n ⠿ 3acdddb9790a Pull complete 13.9s\n ⠿ 9a938759f2bf Pull complete 14.1s\n ⠿ 5d65a6241248 Pull complete 14.2s\n ⠿ cee6999f074e Pull complete 14.4s\n ⠿ 20b12472cb73 Pull complete 14.8s\n ⠿ 65467bb36f5f Pull complete 16.2s\n ⠿ fe6050bae51d Pull complete 17.4s\n ⠿ 519306d43b4a Pull complete 17.9s\n ⠿ erc20-watcher-db Pulled 15.0s\n ⠿ 8921db27df28 Already exists 0.0s\n ⠿ eb286326f602 Pull complete 0.3s\n ⠿ 63139c77dd7e Pull complete 0.5s\n ⠿ 17baeacd3984 Pull complete 13.5s\n ⠿ 5f08b9782916 Pull complete 13.8s\n ⠿ a836be7ad658 Pull complete 14.0s\n ⠿ 1966853affaf Pull complete 14.2s\n ⠿ 4dc6d2c8dede Pull complete 14.4s\n[+] Running 8/8\n ⠿ Network laconic-30c27a9be20b005274dfc23fd7e90256_default Created 0.1s\n ⠿ Volume \"laconic-30c27a9be20b005274dfc23fd7e90256_erc20_watcher_db_data\" Created 0.0s\n ⠿ Container laconic-30c27a9be20b005274dfc23fd7e90256-ipld-eth-db-1 Healthy 33.0s\n ⠿ Container laconic-30c27a9be20b005274dfc23fd7e90256-erc20-watcher-db-1 Healthy 34.8s\n ⠿ Container laconic-30c27a9be20b005274dfc23fd7e90256-migrations-1 Started 32.7s\n ⠿ Container laconic-30c27a9be20b005274dfc23fd7e90256-go-ethereum-1 Started 33.1s\n ⠿ Container laconic-30c27a9be20b005274dfc23fd7e90256-ipld-eth-server-1 Healthy 53.5s\n ⠿ Container laconic-30c27a9be20b005274dfc23fd7e90256-erc20-watcher-1 Started 54.3s",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Let's take stock of what just happened, we:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "list",
|
||
"style": "bulleted",
|
||
"children": [
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "cloned a bunch of repos: `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "laconic-so setup-repositories"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "`"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "built all of their docker images: `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "laconic-so build-containers"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "`"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "deployed these images as services that know about each other: `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "laconic-so deploy-system up"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "`"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Take a look at all the running docker containers:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "docker ps",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "You should see 6 containers:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n605ccf0e4461 cerc/watcher-erc20:local \"docker-entrypoint.s…\" 6 minutes ago Up 5 minutes (unhealthy) 0.0.0.0:3002->3001/tcp, 0.0.0.0:9002->9001/tcp laconic-30c27a9be20b005274dfc23fd7e90256-erc20-watcher-1\n0a00a3a1bcd6 cerc/ipld-eth-db:local \"/app/startup_script…\" 6 minutes ago Up 5 minutes laconic-30c27a9be20b005274dfc23fd7e90256-migrations-1\nf4aece866e48 cerc/ipld-eth-server:local \"/app/entrypoint.sh\" 6 minutes ago Up 5 minutes (healthy) 127.0.0.1:8081-8082->8081-8082/tcp laconic-30c27a9be20b005274dfc23fd7e90256-ipld-eth-server-1\nebe0dc8cd2b4 cerc/go-ethereum-foundry:local \"./start-private-net…\" 6 minutes ago Up 5 minutes (healthy) 127.0.0.1:8545-8546->8545-8546/tcp laconic-30c27a9be20b005274dfc23fd7e90256-go-ethereum-1\n72263d100b8c postgres:14-alpine \"docker-entrypoint.s…\" 6 minutes ago Up 6 minutes (healthy) 0.0.0.0:15433->5432/tcp laconic-30c27a9be20b005274dfc23fd7e90256-erc20-watcher-db-1\nd2effc54624c timescale/timescaledb:2.8.1-pg14 \"docker-entrypoint.s…\" 6 minutes ago Up 6 minutes (healthy) 127.0.0.1:8077->5432/tcp laconic-30c27a9be20b005274dfc23fd7e90256-ipld-eth-db-1",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Finally, via the `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "watcher-erc20"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` container, the "
|
||
},
|
||
{
|
||
"url": "https://graphql.org/",
|
||
"meta": [
|
||
{
|
||
"id": "rel",
|
||
"value": "nofollow"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "GraphQL"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": " playground is enabled on "
|
||
},
|
||
{
|
||
"url": "http://localhost:3002/graphql",
|
||
"meta": [
|
||
{
|
||
"id": "rel",
|
||
"value": "nofollow"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "http://localhost:3002/graphql"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": " and you should check that it is there:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Great so now we have the core stack up and running, let's deploy an ERC20 token."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "First, we need the `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "CONTAINER ID"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` of the ERC20 watcher:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "docker ps | grep \"watcher-erc20\"",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Using the `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "ID"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` from the example above, we'll export the `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "CONTAINER_ID"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` for use throughout the rest of the tutorial:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "export CONTAINER_ID=605ccf0e4461",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Next, we can deploy an ERC20 token (currency symbol GLD):"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "docker exec $CONTAINER_ID yarn token:deploy:docker",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "and your output should look like:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "yarn run v1.22.19\n$ hardhat --network docker token-deploy\nDownloading compiler 0.8.0\nCompiled 5 Solidity files successfully\nGLD Token deployed to: 0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\nDeployed at block: 9087 0x4dc63b4b2695b644d7d390d70c9de0232399ea4d54b8c75911eee14c13f9ceaf\nDone in 157.39s.",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Great, now that we've deployed the GLD token, you'll want to export its address for later use:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "export TOKEN_ADDRESS=0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Get your primary account address with:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "docker exec $CONTAINER_ID yarn account:docker",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "and the following output:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "yarn run v1.22.19\n$ hardhat --network docker account\n0x33AF7AB219be47367dfa5A3739e6B9CA1c40cDC8\nDone in 21.63s.",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "export that address to your shell:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "export PRIMARY_ADDRESS=0x33AF7AB219be47367dfa5A3739e6B9CA1c40cDC8",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "To get the latest block hash at any time, run:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "docker exec $CONTAINER_ID yarn block:latest:docker",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "for an output like:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "yarn run v1.22.19\n$ hardhat --network docker block-latest\nBlock Number: 12783\nBlock Hash: 0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\nDone in 21.44s.",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Next we'll configure MetaMask."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "heading",
|
||
"level": 2,
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "MetaMask"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Open MetaMask in your browser:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "list",
|
||
"style": "numbered",
|
||
"children": [
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Click \"Add Network\""
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Scroll to the bottow and click \"Add Network Manually\""
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Put in this information:"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "If you see the error above \"This URL is currently used by the Localhost 8545 Network\", change `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "localhost"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` to `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "127.0.0.1"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "`:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "We will come back to MetaMask later and complete this process; for now, copy your new address"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "and export it for later:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "export RECIPIENT_ADDRESS=0x988a070c97D33a9Dfcc134df5628b77e8B5214ad",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "heading",
|
||
"level": 2,
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "GraphQL"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Head on over to "
|
||
},
|
||
{
|
||
"url": "http://localhost:3002/graphql",
|
||
"meta": [
|
||
{
|
||
"id": "rel",
|
||
"value": "nofollow"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "http://localhost:3002/graphql"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": " and paste the following (but with your variables):"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "query {\n name(\n blockHash: \"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\"\n token: \"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\"\n ) {\n value\n proof {\n data\n }\n }\n\n symbol(\n blockHash: \"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\"\n token: \"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\"\n ) {\n value\n proof {\n data\n }\n }\n\n totalSupply(\n blockHash: \"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\"\n token: \"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\"\n ) {\n value\n proof {\n data\n }\n }\n}",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "then click \"Run\" and you'll see a response like this:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "{\n \"data\": {\n \"name\": {\n \"value\": \"Gold\",\n \"proof\": {\n \"data\": \"[{\\\"blockHash\\\":\\\"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\\\",\\\"account\\\":{\\\"address\\\":\\\"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\\\",\\\"storage\\\":{\\\"cid\\\":\\\"bagmacgzavwb52aq6smf6movgcimvuoggp3cifayb2vyidg3ar546pwtb3dea\\\",\\\"ipldBlock\\\":\\\"0xf843a032575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85ba1a0476f6c6400000000000000000000000000000000000000000000000000000008\\\"}}}]\"\n }\n },\n \"symbol\": {\n \"value\": \"GLD\",\n \"proof\": {\n \"data\": \"[{\\\"blockHash\\\":\\\"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\\\",\\\"account\\\":{\\\"address\\\":\\\"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\\\",\\\"storage\\\":{\\\"cid\\\":\\\"bagmacgzanp5bxcn6wqd2yptbbwo5o4rx3mhpji43yd7sfd42suq6hjuhuroq\\\",\\\"ipldBlock\\\":\\\"0xf843a03a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19ba1a0474c440000000000000000000000000000000000000000000000000000000006\\\"}}}]\"\n }\n },\n \"totalSupply\": {\n \"value\": \"1000000000000000000000\",\n \"proof\": {\n \"data\": \"{\\\"blockHash\\\":\\\"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\\\",\\\"account\\\":{\\\"address\\\":\\\"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\\\",\\\"storage\\\":{\\\"cid\\\":\\\"bagmacgzasfla7wzuessejihdtrxqd5lqxc57egukbbricizz2ssrltex4uvq\\\",\\\"ipldBlock\\\":\\\"0xeca0305787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace8a893635c9adc5dea00000\\\"}}}\"\n }\n }\n }\n}",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Here's what it'll look like in the browser:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "A lot has happened thus far, so let's review; we've:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "list",
|
||
"style": "bulleted",
|
||
"children": [
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "downloaded the core repos, built their docker images, and launched a local network (all using stack orchestrator)"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "deployed an ERC20 token, added it to our MetaMask account"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "used the GraphQL playground to query the ERC20 watcher"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "listItem",
|
||
"children": [
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "exported a handful of shell variables which are about to come in handy"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Next we'll use the playground to query account balances:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "query {\n fromBalanceOf: balanceOf(\n # latest block hash\n blockHash: \"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\"\n token: \"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\"\n # primary account having all the balance initially\n # created by stack orchestrator\n owner: \"0x33AF7AB219be47367dfa5A3739e6B9CA1c40cDC8\"\n ) {\n value\n proof {\n data\n }\n }\n toBalanceOf: balanceOf(\n blockHash: \"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\"\n token: \"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\"\n # address copied from MetaMask, has no balance initially\n owner: \"0x988a070c97D33a9Dfcc134df5628b77e8B5214ad\"\n ) {\n value\n proof {\n data\n }\n }\n}",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "the primary address should have "
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong",
|
||
"emphasis"
|
||
],
|
||
"value": "value"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": " 1000000000000000000000 and the recipient address should have 0:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "{\n \"data\": {\n \"fromBalanceOf\": {\n \"value\": \"1000000000000000000000\",\n \"proof\": {\n \"data\": \"{\\\"blockHash\\\":\\\"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\\\",\\\"account\\\":{\\\"address\\\":\\\"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\\\",\\\"storage\\\":{\\\"cid\\\":\\\"bagmacgzarsopkngjoijjyktfhgckq7te4dsk25gfyj653uxu4kcwqoyuykiq\\\",\\\"ipldBlock\\\":\\\"0xeca031bcbb6b5a44c97488b8904a85b2396b1cf337ff3ee4efb0ea1ef5104325dbfc8a893635c9adc5dea00000\\\"}}}\"\n }\n },\n \"toBalanceOf\": {\n \"value\": \"0\",\n \"proof\": {\n \"data\": \"{\\\"blockHash\\\":\\\"0xb7b4b65dd5fe3800a6c38cb8a26249bbb82041d7e0b347a853b73efc7a473b75\\\",\\\"account\\\":{\\\"address\\\":\\\"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\\\",\\\"storage\\\":{\\\"cid\\\":\\\"\\\",\\\"ipldBlock\\\":\\\"0x\\\"}}}\"\n }\n }\n }\n}",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Note also that the recipient address also does not yet have a `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "cid"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` or `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "ipldBlock"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "`, which makes sense; this is a random account we just created and hasn't received any transactions. The network does not know about it."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Let's send it some GLD!"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "docker exec $CONTAINER_ID yarn token:transfer:docker --token $TOKEN_ADDRESS --to $RECIPIENT_ADDRESS --amount 100000000 ",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "You'll see a familiar output:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "yarn run v1.22.19\n$ hardhat --network docker token-transfer --token 0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550 --to 0x988a070c97D33a9Dfcc134df5628b77e8B5214ad --amount 100000000\nNothing to compile\nTransfer Event at block: 13371 0x412dbc25599773bfe929c67882e4a001b9d1b3b8e1c60ad4a495d5306608c77a\nfrom: 0x33AF7AB219be47367dfa5A3739e6B9CA1c40cDC8\nto: 0x988a070c97D33a9Dfcc134df5628b77e8B5214ad\nvalue: 100000000\nDone in 26.12s.",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Now get the latest block hash:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "docker exec $CONTAINER_ID yarn block:latest:docker ",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "and go back to the GraphQL playground. If you've changed nothing since the last query, update only the latest block hash and run the query again, you'll see the updated account balances:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "{\n \"data\": {\n \"fromBalanceOf\": {\n \"value\": \"999999999999900000000\",\n \"proof\": {\n \"data\": \"{\\\"blockHash\\\":\\\"0xec173c3aac86a533710569340a4ffb3f3e2d46080e35b034e93ec0049cc12174\\\",\\\"account\\\":{\\\"address\\\":\\\"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\\\",\\\"storage\\\":{\\\"cid\\\":\\\"bagmacgzahg5shtf2rr7pompx7yx6r22zu4lea7ftlnbqkqcabvndsrvoljhq\\\",\\\"ipldBlock\\\":\\\"0xeca031bcbb6b5a44c97488b8904a85b2396b1cf337ff3ee4efb0ea1ef5104325dbfc8a893635c9adc5d8aa1f00\\\"}}}\"\n }\n },\n \"toBalanceOf\": {\n \"value\": \"100000000\",\n \"proof\": {\n \"data\": \"{\\\"blockHash\\\":\\\"0xec173c3aac86a533710569340a4ffb3f3e2d46080e35b034e93ec0049cc12174\\\",\\\"account\\\":{\\\"address\\\":\\\"0x0Dcb65938A483547835e2ebB4FC6cBf7AEe77550\\\",\\\"storage\\\":{\\\"cid\\\":\\\"bagmacgzas6xotntgq4u3v4eui6pmtbyttgikzmu7mppknam2wrekhoynupjq\\\",\\\"ipldBlock\\\":\\\"0xe7a03305adb1a8efab310b21e03d5a9f08d8cf98815372c2c4d8068e1359b8f996bc858405f5e100\\\"}}}\"\n }\n }\n }\n}",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Great, you've now used a watcher to see query token balances."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Let's send some tokens from the MetaMask recipient account back to the primary account."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Recall that when adding the network to MetaMask, we used the currency symbol \"GLD\". However, this does not mean that MetaMask can auto-detect the token, therefore, we will have to manually import it:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Copy the `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "TOKEN_ADDRESS"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "` and paste it in the popup. The two other fields should auto-complete:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Click \"Import Token\""
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "and now you'll see your balance. Ignore the GLD token from earlier."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Finally, send some tokens back to the primary address using MetaMask:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Make the gas price `"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"marks": [
|
||
"strong"
|
||
],
|
||
"value": "0"
|
||
},
|
||
{
|
||
"type": "span",
|
||
"value": "`:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Grab the latest block hash (again) and fire off the GraphQL query for account balances to see the change."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Voila! You've successfully stood up the core Laconic stack, deployed an ERC20 token, and queried account balances."
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "heading",
|
||
"level": 2,
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Cleanup"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Tear down your docker containers with:"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"code": "./laconic-so deploy-system --stack erc20 down",
|
||
"type": "code"
|
||
},
|
||
{
|
||
"type": "heading",
|
||
"level": 2,
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Next steps"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "paragraph",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "Try out the "
|
||
},
|
||
{
|
||
"url": "https://github.com/cerc-io/stack-orchestrator/tree/main/app/data/stacks/erc721",
|
||
"meta": [
|
||
{
|
||
"id": "target",
|
||
"value": "_blank"
|
||
}
|
||
],
|
||
"type": "link",
|
||
"children": [
|
||
{
|
||
"type": "span",
|
||
"value": "ERC721 demo"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
},
|
||
"date": "2023-01-31",
|
||
"featured": false,
|
||
"id": "64023526",
|
||
"image": {
|
||
"url": "https://www.datocms-assets.com/66113/1675106863-laconic_clippy_watcher_02.png"
|
||
},
|
||
"slug": "copy-a",
|
||
"title": "COPY A"
|
||
}
|
||
}
|
||
} |