From 2ab0818cbede3a1f7863a44cd6eef608eec782f2 Mon Sep 17 00:00:00 2001 From: Yoseph Kurnia Soenggoro Date: Mon, 17 Jul 2023 15:57:51 +0700 Subject: [PATCH 1/3] initial indexing erc6551 page setup --- pages/_meta.json | 1 + pages/advanced/_meta.json | 3 ++ pages/advanced/indexing-erc6551.mdx | 55 +++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 pages/advanced/_meta.json create mode 100644 pages/advanced/indexing-erc6551.mdx diff --git a/pages/_meta.json b/pages/_meta.json index 5d9aac4..aa80e54 100644 --- a/pages/_meta.json +++ b/pages/_meta.json @@ -8,6 +8,7 @@ }, "sdk": "SDK", "contracts": "Contracts", + "advanced": "Advanced", "eip": { "title": "ERC-6551", "type": "page", diff --git a/pages/advanced/_meta.json b/pages/advanced/_meta.json new file mode 100644 index 0000000..bba1748 --- /dev/null +++ b/pages/advanced/_meta.json @@ -0,0 +1,3 @@ +{ + "indexing-erc6551": "Indexing ERC6551" +} diff --git a/pages/advanced/indexing-erc6551.mdx b/pages/advanced/indexing-erc6551.mdx new file mode 100644 index 0000000..954328b --- /dev/null +++ b/pages/advanced/indexing-erc6551.mdx @@ -0,0 +1,55 @@ +import { Callout } from "nextra-theme-docs"; + +# Frequently Asked Questions + +### What is a Token Bound Account (TBA)? + +A "Token Bound Account" is a smart contract account, controlled by an NFT. It can do everything a normal wallet can do and is compatible with every NFT you already own. + +### Why now for ERC-6551 and Token Bound Accounts? + +Hundreds of thousands of NFT projects have launched in the last few years, from CC0 projects to multi-billion dollar media/entertainment companies. NFTs have reached mainstream appeal over the last 2 years. However, ERC-721, the token standard that coined the term NFTs, has remained roughly the same since it was created 6 years ago. The standard didn’t/couldn’t anticipate all the potential use cases when it was conceived in 2017. + +One such use case is ownership from a token level. NFTs and most tokens are assets that are owned and controlled by a wallet, typically that is Metamask, Rainbow, Coinbase, Ledger, etc. but as NFTs have grown into full blown communities, the demand for utility and general usefulness has reached new heights. Projects with enough capital often organize IRL social gatherings that require huge amounts of capital and resources. Projects with less capital pursue on-chain game mechanics such as staking, farming, airdrops, voting, and purchasing. + +However most of these mechanics are often difficult to build and as a result each project has their own implementation that essentially does the same thing as the other but has more potential security vulnerabilities. The concept of ERC-6551 and Token Bound Accounts allow NFTs to have its own ethereum identity in the form of a smart contract wallet. ERC-6551 will allow for all NFT projects to add in important utilities to their tokens without heavy capital investment and effectively leveling up the entire NFT asset class together. + +### I’ve seen other projects where NFTs can own assets. How is ERC-6551 different? + +ERC-6551 focuses on ease of use and adoption. Unlike other proposals and projects, Token Bound works with no action needed by project owners, no wrapping contracts, and no change to the ERC-721 standard. Most importantly, every ERC-721 and ERC-1155 NFT you already own works with Token Bound Accounts — projects and creators don’t need to deploy a whole new contract to use Token Bound, and you can start using ERC-6551 immediately. + +### Why is ERC-6551 important? Why should I care? + +Digital collectibles/art are the future of creation. More than ever, people around the world are using technology to create digital goods such as NFTs. ERC-6551 is the most effective way to increase the surface area of interaction for NFTs. It was designed to be easily adopted by existing marketplaces, wallets, and dapps. It is permissionless and decentralized so that no single company owns your NFT’s wallet. When it comes to token provenance ERC-6551 allows your NFT to have an on-chain identity where history is created from the NFT itself rather than your wallet. + +### How do I know if my NFT has an account/wallet address? + +Every NFT already has an Address we can compute using ERC-6551 and Token Bound. You can view the tokens inside of your Token Bound Accounts on https://tokenbound.org/. As adoption grows we are pushing for further integration into wallet apps such as Metamask, Rainbow Wallet, Coinbase, and marketplaces like OpenSea, Zora, and blur. Our SDK tooling and documentation also make it easy for creators and developers to integrate this functionality right into their own websites and apps. + +### What can I put in my NFT’s token bound account? + +Absolutely anything you would put into your old wallet. ETH, USDC, ERC-20, ERC-721, ERC-1155, and any other tokens you would normally send to your Metamask, Ledger, etc. + +### How can I trust my NFT’s wallet? + +We take security seriously and we have already completed a preliminary audit with 0xMacro. We will be conducting an additional audit with Certik (with support from our contributing partner Manifold), and seeking additional coverage through Code4rena. + +### Can I nest my Token Bound NFTs inside of each other? + +Yes! Since every NFT is a Token Bound Account, there are no limits to how many tokens you may have nested in your NFTs, or how far down you go. If you want to put an NFT inside of an NFT inside of an NFT you can. When you transfer that NFT to someone else, everything inside automatically goes along with it. This opens up many new patterns of bundling NFTs together for trading, gaming, governance and more. + +### How do I use ERC-6551 for my project? + +The ERC-6551 reference implementation is open source and can be used by any project. Tokebound also provides open-source tooling that makes it much easier for dapps to integrate. If you'd like to learn more about how to integrate ERC-6551 into your project, please join the [working group](https://t.me/tokenbound) + +### What are some of the core use cases for ERC 6551? + +The possibilities are endless when it comes to Token Bound Accounts. However, some clear use cases are as such: + +- Inventory system for owning items, outfits, equipments +- Community loyalty or reputation systems +- Mint or curate baskets of assets (art, collectibles, defi) +- Composable media structures (stems to songs, art layers to painting, digital textiles to garments) +- New on-chain game mechanics +- On-chain meme/derivative economies +- NFTs as onboarding vehicles instead of wallets From 67864d2733830993c39c99004053545768da1e9c Mon Sep 17 00:00:00 2001 From: Yoseph Kurnia Soenggoro Date: Mon, 17 Jul 2023 19:39:47 +0700 Subject: [PATCH 2/3] finish draft for indexing 6551 --- pages/advanced/indexing-erc6551.mdx | 421 ++++++++++++++++++++++++++-- pages/sdk/installation.mdx | 24 +- public/airstack-ai.webp | Bin 0 -> 21400 bytes 3 files changed, 411 insertions(+), 34 deletions(-) create mode 100644 public/airstack-ai.webp diff --git a/pages/advanced/indexing-erc6551.mdx b/pages/advanced/indexing-erc6551.mdx index 954328b..e8b4e6d 100644 --- a/pages/advanced/indexing-erc6551.mdx +++ b/pages/advanced/indexing-erc6551.mdx @@ -1,55 +1,414 @@ -import { Callout } from "nextra-theme-docs"; +import { Tab, Tabs } from "nextra-theme-docs"; -# Frequently Asked Questions +# Indexing ERC6551 -### What is a Token Bound Account (TBA)? +If you need to index ERC6551 on-chain data, you can use [Airstack](https://docs.airstack.xyz) to do so. -A "Token Bound Account" is a smart contract account, controlled by an NFT. It can do everything a normal wallet can do and is compatible with every NFT you already own. +## Get Started -### Why now for ERC-6551 and Token Bound Accounts? +Airstack provides a GraphQL API solution to index [ERC-6551](https://eips.ethereum.org/EIPS/eip-6551) accounts on both Ethereum and Polygon. -Hundreds of thousands of NFT projects have launched in the last few years, from CC0 projects to multi-billion dollar media/entertainment companies. NFTs have reached mainstream appeal over the last 2 years. However, ERC-721, the token standard that coined the term NFTs, has remained roughly the same since it was created 6 years ago. The standard didn’t/couldn’t anticipate all the potential use cases when it was conceived in 2017. +You can try using Airstack now to index [ERC-6551](https://eips.ethereum.org/EIPS/eip-6551) accounts by using the [Airstack Explorer](https://app.airstack.xyz/explorer). -One such use case is ownership from a token level. NFTs and most tokens are assets that are owned and controlled by a wallet, typically that is Metamask, Rainbow, Coinbase, Ledger, etc. but as NFTs have grown into full blown communities, the demand for utility and general usefulness has reached new heights. Projects with enough capital often organize IRL social gatherings that require huge amounts of capital and resources. Projects with less capital pursue on-chain game mechanics such as staking, farming, airdrops, voting, and purchasing. +For production, the Airstack GraphQL endpoint is available at https://api.airstack.xyz/graphql. -However most of these mechanics are often difficult to build and as a result each project has their own implementation that essentially does the same thing as the other but has more potential security vulnerabilities. The concept of ERC-6551 and Token Bound Accounts allow NFTs to have its own ethereum identity in the form of a smart contract wallet. ERC-6551 will allow for all NFT projects to add in important utilities to their tokens without heavy capital investment and effectively leveling up the entire NFT asset class together. +### Airstack SDK -### I’ve seen other projects where NFTs can own assets. How is ERC-6551 different? +Airstack provides two official SDKs to help you index [ERC-6551](https://eips.ethereum.org/EIPS/eip-6551) accounts in your application: -ERC-6551 focuses on ease of use and adoption. Unlike other proposals and projects, Token Bound works with no action needed by project owners, no wrapping contracts, and no change to the ERC-721 standard. Most importantly, every ERC-721 and ERC-1155 NFT you already own works with Token Bound Accounts — projects and creators don’t need to deploy a whole new contract to use Token Bound, and you can start using ERC-6551 immediately. +- [Airstack React SDK](https://www.npmjs.com/package/@airstack/airstack-react) +- [Airstack Python SDK](https://pypi.org/project/airstack/) -### Why is ERC-6551 important? Why should I care? +#### Install SDK -Digital collectibles/art are the future of creation. More than ever, people around the world are using technology to create digital goods such as NFTs. ERC-6551 is the most effective way to increase the surface area of interaction for NFTs. It was designed to be easily adopted by existing marketplaces, wallets, and dapps. It is permissionless and decentralized so that no single company owns your NFT’s wallet. When it comes to token provenance ERC-6551 allows your NFT to have an on-chain identity where history is created from the NFT itself rather than your wallet. + + -### How do I know if my NFT has an account/wallet address? +```bash +pnpm install @airstack/airstack-react +``` -Every NFT already has an Address we can compute using ERC-6551 and Token Bound. You can view the tokens inside of your Token Bound Accounts on https://tokenbound.org/. As adoption grows we are pushing for further integration into wallet apps such as Metamask, Rainbow Wallet, Coinbase, and marketplaces like OpenSea, Zora, and blur. Our SDK tooling and documentation also make it easy for creators and developers to integrate this functionality right into their own websites and apps. + + -### What can I put in my NFT’s token bound account? +```bash +yarn add @airstack/airstack-react +``` -Absolutely anything you would put into your old wallet. ETH, USDC, ERC-20, ERC-721, ERC-1155, and any other tokens you would normally send to your Metamask, Ledger, etc. + + -### How can I trust my NFT’s wallet? +```bash +npm install @airstack/airstack-react +``` -We take security seriously and we have already completed a preliminary audit with 0xMacro. We will be conducting an additional audit with Certik (with support from our contributing partner Manifold), and seeking additional coverage through Code4rena. + + -### Can I nest my Token Bound NFTs inside of each other? +```bash +pip3 install airstack asyncio +``` -Yes! Since every NFT is a Token Bound Account, there are no limits to how many tokens you may have nested in your NFTs, or how far down you go. If you want to put an NFT inside of an NFT inside of an NFT you can. When you transfer that NFT to someone else, everything inside automatically goes along with it. This opens up many new patterns of bundling NFTs together for trading, gaming, governance and more. + + -### How do I use ERC-6551 for my project? +#### Call Your First Query -The ERC-6551 reference implementation is open source and can be used by any project. Tokebound also provides open-source tooling that makes it much easier for dapps to integrate. If you'd like to learn more about how to integrate ERC-6551 into your project, please join the [working group](https://t.me/tokenbound) +To get your Airstack API key, go to https://app.airstack.xyz/profile-settings/api-keys -### What are some of the core use cases for ERC 6551? + + -The possibilities are endless when it comes to Token Bound Accounts. However, some clear use cases are as such: +```jsx +import { init, useQuery } from "@airstack/airstack-react"; -- Inventory system for owning items, outfits, equipments -- Community loyalty or reputation systems -- Mint or curate baskets of assets (art, collectibles, defi) -- Composable media structures (stems to songs, art layers to painting, digital textiles to garments) -- New on-chain game mechanics -- On-chain meme/derivative economies -- NFTs as onboarding vehicles instead of wallets +// Initialize the React SDK +init("YOUR_AIRSTACK_API_KEY"); + +const query = `YOUR_QUERY`; + +const Component = () => { + const { data, loading, error } = useQuery(query, {}, { cache: false }); + + if (error) console.log(error); + + if (loading) return
Loading...
; + + if (data) { + return ( + //Your React UI Component + ); + } +}; +``` + +
+ + +```python +import asyncio +from airstack.execute_query import AirstackClient + +api_client = AirstackClient(api_key='YOUR_AIRSTACK_API_KEY') + +query = "YOUR_QUERY" + +async def main(): + execute_query_client = api_client.create_execute_query_object( + query=query) + + query_response = await execute_query_client.execute_query() + + print(query_response.data) + +asyncio.run(main()) +``` + + +
+ +### Airstack AI + +You can use [Airstack AI Assistant](https://docs.airstack.xyz/airstack-docs-and-faqs/get-started/airstack-ai) to help you construct your query easily using natural languages. + +Go to the [Airstack Explorer](https://app.airstack.xyz/explorer) to try it out. + +Airstack AI UI + +Here are a few example prompts that you can try: + +- [Show the most recent 10 6551 accounts on Ethereum and Polygon](https://app.airstack.xyz/ha8qvF/cyapsZc2O6) +- [Show me all @Sapienz ERC6551 accounts and their balances](https://app.airstack.xyz/ha8qvF/uqLmTIlW7o) +- [Show all ERC65111 accounts owned by @BoredApeYachtClub and the token balances](https://app.airstack.xyz/ha8qvF/CRcpv04wq4) +- [Show sapienz_0.lens ERC6551 accounts](https://app.airstack.xyz/ha8qvF/Kf6QGAUiaF) +- [Show me 6551 accounts created on July 12, 2023, on Ethereum](https://app.airstack.xyz/ha8qvF/qwcEcAqxbT) + +## Examples + +### Get the most recently created ERC-6551 accounts on Ethereum and Polygon + + + + +```graphql +query MyQuery { + ethereum: Accounts( + input: { + filter: { standard: { _eq: ERC6551 } } + blockchain: ethereum + order: { createdAtBlockTimestamp: DESC } + limit: 200 + } + ) { + Account { + id + standard + blockchain + tokenAddress + tokenId + address { + identity + } + registry + implementation + salt + createdAtBlockNumber + createdAtBlockTimestamp + creationTransactionHash + deployer + updatedAtBlockNumber + updatedAtBlockTimestamp + } + } + polygon: Accounts( + input: { + filter: { standard: { _eq: ERC6551 } } + blockchain: polygon + order: { createdAtBlockTimestamp: DESC } + limit: 1 + } + ) { + Account { + id + standard + blockchain + tokenAddress + tokenId + address { + identity + } + registry + implementation + salt + createdAtBlockNumber + createdAtBlockTimestamp + creationTransactionHash + deployer + updatedAtBlockNumber + updatedAtBlockTimestamp + } + } +} +``` + + + + +```json +{ + "data": { + "ethereum": { + "Account": [ + { + "id": "a304f27b838f47353a0e7282e935588e02086d88b62bd93f6857c5f38a530dea", + "standard": "ERC6551", + "blockchain": "ethereum", + "tokenAddress": "0xb6a37b5d14d502c3ab0ae6f3a0e058bc9517786e", + "tokenId": "599", + "address": { + "identity": "0x5bb5b498ff300e2ed23804443d340c7418fab4c4" + }, + "registry": "0x02101dfb77fde026414827fdc604ddaf224f0921", + "implementation": "0x2d25602551487c3f3354dd80d76d54383a243358", + "salt": "0", + "createdAtBlockNumber": 17713013, + "createdAtBlockTimestamp": "2023-07-17T12:35:11Z", + "creationTransactionHash": "0x0102df35f0b9e07f2c375ea6ab37838251ce43d0b8da3bfb39d02d70cd5f8cea", + "deployer": "0x186bad94057591918c3265c4ddb12874324be8ac", + "updatedAtBlockNumber": 17713013, + "updatedAtBlockTimestamp": "2023-07-17T12:35:11Z" + } + ] + }, + "polygon": { + "Account": [ + { + "id": "05bb6fa00c99e9aceca905c7b3c0adbbbe4c463d9cd21e46986156b8075e0704", + "standard": "ERC6551", + "blockchain": "polygon", + "tokenAddress": "0xed97678450405fc37fcd08f026c0bbdc3af835f2", + "tokenId": "58", + "address": { + "identity": "0xc44f0f48b14dd230cd694a268a442ffb198b36b1" + }, + "registry": "0x02101dfb77fde026414827fdc604ddaf224f0921", + "implementation": "0x2d25602551487c3f3354dd80d76d54383a243358", + "salt": "0", + "createdAtBlockNumber": 45187150, + "createdAtBlockTimestamp": "2023-07-17T12:35:50Z", + "creationTransactionHash": "0x8cb955fc174f9198a753c64953acbb1692c2739839280599b491c400cf7c2918", + "deployer": "0x58d8c0efc5b006e4686b15bcdd6ae9517ddaa788", + "updatedAtBlockNumber": 45187150, + "updatedAtBlockTimestamp": "2023-07-17T12:35:50Z" + } + ] + } + } +} +``` + + + + +### Get all ERC6551 accounts owned by a given [Sapienz](https://etherscan.io/token/0x26727ed4f5ba61d3772d1575bca011ae3aef5d36) NFT and their token holdings + + + + +```graphql +query MyQuery { + Accounts( + input: { + filter: { + tokenAddress: { _eq: "0x26727ed4f5ba61d3772d1575bca011ae3aef5d36" } + tokenId: { _eq: "0" } + } + blockchain: ethereum + limit: 50 + } + ) { + Account { + address { + addresses + } + implementation + registry + salt + standard + updatedAtBlockNumber + updatedAtBlockTimestamp + createdAtBlockNumber + createdAtBlockTimestamp + creationTransactionHash + deployer + } + } +} +``` + + + + +```json +{ + "data": { + "Accounts": { + "Account": [ + { + "address": { + "addresses": [ + "0x5416e5dc14caa0950b2a24ede1eb0e97c360bcf5" + ], + "tokenBalances": [ + { + "amount": "1", + "tokenType": "ERC721", + "tokenAddress": "0x8ee9a60cb5c0e7db414031856cb9e0f1f05988d1", + "tokenId": "9707", + "formattedAmount": 1 + }, + { + "amount": "1", + "tokenType": "ERC1155", + "tokenAddress": "0xafda8953da1099a38a6de2aeeb181cd360beb22e", + "tokenId": "1", + "formattedAmount": 1 + }, + { + "amount": "1", + "tokenType": "ERC1155", + "tokenAddress": "0xafda8953da1099a38a6de2aeeb181cd360beb22e", + "tokenId": "7", + "formattedAmount": 1 + } + ] + }, + "implementation": "0x2d25602551487c3f3354dd80d76d54383a243358", + "registry": "0x02101dfb77fde026414827fdc604ddaf224f0921", + "salt": "0", + "standard": "ERC6551", + "updatedAtBlockNumber": 17213826, + "updatedAtBlockTimestamp": "2023-05-08T05:53:59Z", + "createdAtBlockNumber": 17213826, + "createdAtBlockTimestamp": "2023-05-08T05:53:59Z", + "creationTransactionHash": "0xf998cb400eebe89aa1d369792daf4c202be74dcd88981b34eb49d510b7837332", + "deployer": "0xa75b7833c78eba62f1c5389f811ef3a7364d44de" + } + ] + } + } +} +``` + + + + +### Get NFT that owns TBA account with Lens Profile [sapienz_0.lens](https://lenster.xyz/u/sapienz_0) + + + + +```graphql +query MyQuery { + Accounts( + input: { + filter: { address: { _eq: "sapienz_0.lens" } } + blockchain: ethereum + limit: 50 + } + ) { + Account { + nft { + address + tokenId + contentValue { + image { + original + } + } + } + } + } +} +``` + + + + +```json +{ + "data": { + "Accounts": { + "Account": [ + { + "nft": { + "address": "0x26727ed4f5ba61d3772d1575bca011ae3aef5d36", + "tokenId": "0", + "contentValue": { + "image": { + "original": "https://assets.airstack.xyz/image/nft/1/0x26727ed4f5ba61d3772d1575bca011ae3aef5d36/0/original_image.gif" + } + } + } + } + ] + } + } +} +``` + + + + +## Developer Support + +If you have any questions or need help regarding your queries on [ERC-6551](https://eips.ethereum.org/EIPS/eip-6551) accounts, please join our Airstack's [Telegram](https://t.me/+1k3c2FR7z51mNDRh) group. + +## More resources + +- [ERC6551 Query Templates](https://docs.airstack.xyz/airstack-docs-and-faqs/guides/token-bound-accounts) +- [API Reference](https://docs.airstack.xyz/airstack-docs-and-faqs/api-references/api-reference/accounts-api) diff --git a/pages/sdk/installation.mdx b/pages/sdk/installation.mdx index 60bed2d..a6eca01 100644 --- a/pages/sdk/installation.mdx +++ b/pages/sdk/installation.mdx @@ -8,9 +8,27 @@ The Tokenbound SDK is compatible with viem and Ethers. Install the correct versi Note: If making use of one of the many Web3 starter kits, please make sure that you're using a recent release of viem (>1.0), Ethers 5.7+, or 6 to avoid issues. - ```bash pnpm install @tokenbound/sdk ``` - ```bash yarn add @tokenbound/sdk ``` - ```bash npm install @tokenbound/sdk ``` + + +```bash +pnpm install @tokenbound/sdk +``` + + + + +```bash +yarn add @tokenbound/sdk +``` + + + + +```bash +npm install @tokenbound/sdk +``` + + ## Example apps diff --git a/public/airstack-ai.webp b/public/airstack-ai.webp new file mode 100644 index 0000000000000000000000000000000000000000..2fbfe2d8cb46f64e54d1ad996465adbf69816118 GIT binary patch literal 21400 zcmV)KK)SzDNk&GHQvd*0MM6+kP&iD3Qvd)jKgKi=RSP4xZ6hUiJ^%l62U*bV8W9s< zr}b^e;(M6^27S9|TnQiTzsb!j;P>#?f?{-Fg9>H1xsnPah{DeqIU~qe3uw5C4gr*Ci!K;b zct8MBu!)0u|wr!-pqT04? z+y0HVZR2RPXADTHwe69VeNKN>=Ss7YU3Y)2sjJ^5pbGPP@LKbB-UgYZ6rY%GDqb3 z6Z!hfzl32MDRRS74p_cj(tkH@BRLY=?C!bn9x&aJoB#k7ySXrb4%3t}Gcz+YGliL% zIgZ^tQH_engrB;M{FZ0 zlC!(V%zSUn)Aql+6FKeFlRA?G$`VJ?5sD~F2npqYkWfZKCF-8FLJmB-l=sG?7Yvvi_N{hVHB8>-B7KwUMvJOip~AI;LjL1wVV zIftg@&{~-)#^G0oYUgZEpykAlDkiDk3A+SkN=1#Fvs+)Mm$fqtrE)Kw5mfaV?WRgj zM--)T_T(9jBRi@lzIA5Q&OudlwZvJmazGCFbZ5kEn>^_2z}cFv@+45#csI@n zhojx(@CvHrZ1-d)k5&`p^b=k3F3E#srq7BMRg-z0vrPwCIA?b?ABQ8nY8UJ8{FZl01Q~s*Yk;eyz%i%4%o~G=nnZ2&%KHC=9yH zENeT4&;Y8Q)LlBZ+|Sk3RdU0mx@tdJ%`gU*0as?l5LR`}t!7X(0OmHFGFJx$Ns<&v zl0#r-)!-ie|Do4^NNgl2lAOnwi#YRDJ5t`14J)F zGh&y$2uZ1n4#*+fA#2hbqZvg|!V6gxK<=8K6l>^5)mWs_NwMgrhy(!u$Tq5N+n!O|HZt3`9TsQXkGkJDZretXEGcvMzW$57{<~o# zNs&DFO#RW}?p~~&8Nt#?+#j;!1lX!Uj)ODs>iDOFgdgNF7(-R0?Ol9j$(KCUftjXc z;pVga9DE02$olKdjnZg%deMh4g1Q+3_etCYc1ZkheJdVzGu#N-mk}_L1xyHkfg*Z= z7qYGCXaB`J3cy#Oi7fBZ8M`mBhh#|MF7OwKq7m*ckatQX6lMciG)D?MEJ=Vk33Sor zL#z0f33Gukn#+{5xV{RMk9)y4TFrN62`;YsN`;YsN`;YsN`;Yr? zivPI(il~QeyjHB0ua(zt0G%?kpP~do%DQkn@RmV4+(a4!=r#u$Ph}5X1fwV|Q0XCj zb*#>OS+qUpoG`(mB0VFH* zA`3F-#>TE%?~ZVWKwOBTl8A;YP>`?-pU-DiN#+w?&K?U*6Xy7VlhL81z=~ciG2_&h z{fMd;RTV`MP@<@!YNDvN=+!1{M7Vf5qHOZkLvg1A2kG4B{IpIo6#x-F7N%woJ0Xe! z>kJu<#UEy>%45J2RS{X1`S;>YokGjh(K$WzKtDvCnAq~2By(-DkTnMOd38*Fz=UH=$iIsHpDvJD&nneKoxWPu>~^b z0k!+=a9Kxq6rai0Ue<|)n@QrUq?chL#IR}lp(PBsNdGcoCTgjfbty)^MuDe=_lEke zMlK%;Fc!il44PS_d$-0Z6D~$#W4Nq{8`Qz?s@MJokC~8H9v~M^a1mo!XPK@z^Ga+3 zvQ!NkiZtbcD+$TKS>8n~{jjbR3lEdTSTR3yWz~omp@N$KY_QQZnYeEGHc+eeluXN8 z+j-F7|INye?0zoi31C*6yF?8A_(SRe1Mmzni;gwMa zSupND?!R*X@t&!G!_nbFFzTQMgO+QW#kDsSj5rA1$Bj*iF3_WP6#Tm$ce1}p??`gI zI9f3HCMZCK;>hRt@j%eFSU;bwyF7;fl{otdZeQL43RAaeV>FIHyGJe}7uIJU*r z6DhjmC>Ru#n-onL&f#4@Ztjh3&!4{cz3+M6ZHeG9Kne_6s%x@ca4tbBpGJLqHbsn%m1_2EHW8+I|&@!)8Sq3%0942v8DIIsa<9O zx}fUyGMbD;g=UZl8bMu58jr2L7M#K3*1^JSUQ27-FfQ0WI8L}uIWAc|&U4LbIRIdI zobO!T^5f#2A?8_1u5Pt%Sc+64Ay=&PJEXw^s9oHekcW#qSUiS2C;sfrY^kHr+ESv; z#@SNoF)le+e6DZJ)Bv0dj@~T;0E`xogLyy7ps727r49mtMBFK3ExBlJZV7c|NjRP+ zr=X8Jz1`EtU0y9-Uz?By|8kA5lc>cadTLybcE|WH{p7wF09MTc0IH1he@6HM!UdXf!~jyF2x!o>`l6 z*|BU1m6Uz4SM|v{O{h$7MMnUJ~hIQePzC_qV}uCojVP>WSf z9I(vQH;uv7on?ne!3zfHFGo!Gfb%usmW0T$S2}{~Hy=exS|oTLAnDf>;WBUfR=qM5 zL9qVwkTS3?BHm1J8H%E9iUIj85!GEti1E0;DfuuAA$)hY`^HVlB(8+c6>Y`IwjZ(^ zDde!~DBos=>Tw0zb4ASFYhyCwFFjWxzKa2~HyY>f z2FE^ZVILhCK&lSRE#V~US$sJ|guE~Pf>Q%b4VZ98E~{*h(^mPK0u$A z4GotWRE@UsS`aw7lTu|{1=$F09s=P2rENTyI7dfGXx|Strup1~h%b^^a9|34{(d=R*B{AgD#}P&me3bqx{r_yIoi8m#6BC6vQIa!`x*&WdiFZ>HuTPB_6JglcX zDn!-*x>e5C(@N-_zr@7Dk=z5v5*}j0_HrUIOe4b)hM0I9R0I*4kRCO2059#tHo7ESaTEx`Oh$)ZA1^+F-bfTf0NgjFC@nZ)faN8XJU zu!v5~L~hj_N2JFNrp8)%D-!6HlSYjsyHgwlP+zxM$FM6qOc5W+!N0!;u?S2IMMW+u z3Na!Yr-H1;0o}lKa516ajvarj|4a4z2?t-<@4w7dJZT5e`#r;rktK%uso|AiM96oc zMn1|5h0lLBY#wqPd9~UD{@KQDPKgO~s776YKDb$BMEO7nII$+l`lKtQ6*UP5e2{v~ z|0|vJewQNCkCjPUySWF$IJV=%K1-|;!_11oEUFr1#GUGko}9^}=Kd>!t_-$eOMLy@ z7}I}5(N9eS>B)0pERU&~cZR5o#+>@ZSe3YP4alV;P;N>?Mr ziM-WuRCuk&aAFl4Rmr=0kf`}q1to0U#(RyyU=XFUzF-lxkT<6IX?ngF0Q>Q?Bt>F% zqi4Q_!E>wSDzhThj~$o28cv1De^wasamDQ=aT`#aAoyU$G+H)?e2aaY2#VvN=X+9# zA{6c7mP{Ka$-ZaO{NfbblIwNqnpeRVs^_*!)INumI1h zpwPk;4t%~8n#V9G8842M+VAepmq z2ptu%PBo!MwNjZXtZ6K@*@UmiuA24fYmKN5mBfNuXoYi+CsORL7S_g$T1@0=-G0V) zRjkiVsA1o-M6DF(<17vh+zc-5lmIoD-jq{jkKadd*rmtZ1wzJ3^71f zFlbCvtbqV#aS;Fj)}EEvv&8MyO@k3DA%zFP+Dce^Bb(K@}S(hwj zEQn?iF$mUYoofsw1lX2Ewz42ake+%uq?|+I09wk$^a(Q(}3w?NQJOOU4;6k2g6EOTY~bTOXoz2 zW(7iN$HBw}hh|;h5m_y4&q`R@m>8`Zv#i7whb0%%Ucy>(TaNOV4~9z3;`^H0v#c#9 zByxHgCUu8v4ueF6A<&^@CPFiR?V|B9Xu{(fEDTACc1_b!U0 zNh?}xX_0DrS?`x}H4^p`gNen!h*cB1iWLl7B)a4Pz%ZD@d)RxWvZSGEN{;CiHN>!pwFPpc+p-dhWU!(d z6#%ITnk=e5x zeQ^UCiWmCcDPCTnZd1M}(ROv^06oZLpFoeEG@}U$m3S++0y8I>K4XSC!`{XP$q?f> z=Q1m2nkCrNMY=Et;LJ&<&5~-xQ1{XEG``$!VuH@-xck?E?El|LIDNz`n$IEBW z0vw`b%LEpFz*y~S1oVwb*+ zz;+Zjh%1X!t)bM~o78HI5m!~^006zm^rDKbg!jQnK2YOC zl3djbM7w4&;Il`}i!0Kmdd>A2OmQzY7qqlVs%l0}zUhx69(>Wp@$(T^IaX~-dSEaB znx=oeONtR+!e|arK<=2Rx%m_rIG3!SdSG>nn@7(}Y5{-=R0hs79@u8{jT-krLL2+5 zqo<@Q`G}rZXDQkGp`+x)D!E)}LMslyZR4-R%zkOF%neOsH`qA5}@JV1#19{MjEO_wm;=WoW;cAPDqn(h?A z%4a9U!d!pkyip2?JKFboi>aWl{pSR-_dWWk1J@$C;aMiW+B;5Kzas{mGBj(d!fz0epi-C*kZlB(wSVa$

)uP|%Z@0sMXNg!g$h%s(Wb-1Nz*KHHk#dqWU9`Lq zONrScY(B*mBub619|7RASD%D^z`NcyW_lzE0q?txHPsw+Jm9Y%W+h7P)d$Jb?b1e% z#Q>b!JF(QhY5|vb{MYwbbJ0nBF)X#=#Cwf^Gz<=srb#WEoRlTQZtkQN`64U;*!riF zt4U_%#4xz(=^o0g_$qTI9@E8<5M(oB0QN3U+b_N3L7VT30i#EndhetXO>JsM$nd65 zamEx9Pt8MUcWms3Xhd%PnS)IQ4m$@2{3*ZXwm1ORrW$oe{KM$dk0D*#|#;TQzAP82yoTgH4Z-0JOu@=Y6c|NmNo5Ma@DendGq|<0LtSEOlOvs!<(w4JdiH#Sna_RN0EDGLulf8* zWUc0}k5}jlGnD)FNl|`Y3Qf9fH()~uw#sUV*^-EPD9C>if}DM7?F#+ zZ%!voL<7*4y|QMqPx-rGIxMF;y$M4#?J_J>!MHBe0nG(lFo-mXkPq24EpMU=Z9q>F z^`%?HYmAeQWnySG-OQLf#sUG_GeHaPw4D=!9qPWZGl14yO4v!aSP&@jY8eY=0A_P_ zEfFtMnE@@!Y~@U}V+}wH{&J5K`!Ge$Xoi4Aw?!8cs_WvcCj`-qJbY)D9~ihyN&3Bz zuh;Z+Uic23#|@24f|A701iodm)yj;p#*a5L98DRV2MnOUmM zBLR{O$g~#3b=0gaDAU8)f9_Xts6rzGXpf{QRKG0%Ne}TJG)Y4kkmJ&Fm%r5a1HIn!yB+ebMw3dJR6m6Ur+0Vhq^nU}Izia1 zCF}L>R3nczm5H$PyD>@YKjNOn6u&1uiBev8^uLi$+m8~|6Q41gF0pQ!McbNHd@Qmd|MoT0{GewAI`!!V-Kor1;MsA;lRH7boh zEc_Q40PUCAMpL1zyi!8NVgR~-^<2_Ug>@N||C*(P=g*+AR<=zqJusMj?upH?22`D)xs;cl%ge9)GF-QOO=bf@g{A-d#UH3_c`06^Pd zSdrGPp{bct@&O;PWDrfI8oJ`&st^Y40D9EbK_8@b={!S|M)X+(V0jG-F43)tX8ERH zn&J@Wr;H%W#n#Q%c)g=b+5WW*fbNgvSS458^Q`jzq#FBydFXs{Y3oYTY!a^2=h*e{ ztc10uQbT_GytdG<;02{QcO3j>YH)X{I)O&4hp|ucG~EJ14}@n(6@+jdZ3BXvUwWd)oG8ov|Z*psT8mScmdGD(e7Mbrr0q zDv5S#Dg;#dRWK6kC~x_q0zDR)>O(<>D$Gf4=Ljm*i)-%wckkxzZ)T;x0ZViP2$!Rv zJaAv;DvD<`S875Q02(GmcRvLBWtgd^<&bd>B9GHM5+F)@N zxY|}Gpj`>yhU4N1Sf&I<#T3PKuzEUx-;qu#>#pqq`)d5vIME9L)M;{cBSgLKOjdw3 z`sT!SJ6saCX8g!EggW(e8p@G2aL?YF(gKVXc&H-+@Cwu;;ty_LmM{i zaOwKmI({cb8fi!PTODJ%Dg%HwD<$1%N1OIDsiJ2SfR4MYQ_n_^#T1)rB$7vV4WnIg z<{d~YM_l#73yXE)KXG20vYA&-@0k^Y+5?kbR6{6^_ReG&ia}EqOkgtWw$il23D+33 z;ZxhTAq#6CQCG;Z3S4L~7-Z^f@nW;u*KVmS=aL0>PYcuYu!W*wc@||vai{h9Mjo2D z+U>1PzxD7#J{u2wq)Az8=0(ifXC7m%Vx^4%v&qEz?tRp*+s99%nr)v_Q7d-pJ!iU} z0Gg+?kP$B!tVmd$ER8vyrX%aRlVh~piJ@?GMd28kbAERarOUN)c^3on#2inx^X+%M zhAgYI>}E&y3uo_~PXA@I^9?;}sM4({om*j@SgmIhQjaicB5NM&-PX&yDj)+aIYyqp z3dkrPnCX^%<<~HPo!z6%Hs)X~gXK=OUi$k7*ygypgsPn$3!t4#Gm?a++1rh#u4e+5 z9Za&};6oWsYYF(SF|f3|7n?iox{%>}2?W&Smk_$)T-rO2w;w*ba}SwWXUo`KzQc2)M#(|dEkhs$kS zhc6P>oJYthl?qduPueA+`qF$LCf8_N(hRVR_oz~d70~_aTAgmnrt7+@G)bSqR5GM1 zmhpn&`j#jrKIHqESrJRxaikNjngMZJi?G;pvEf;aIdNR}|CLIA4qh;541l~c&6NLP zUYj|JJBH0P*v+4NXwu7!oCgL>8q2#hcG;?96zQ(_!Jx{APoI7&cegfc52K1cf^!y_ z>uA_z9+USNQA@X61y^Gy)V;orMF5!9N0GKm+prOeMYGU_2ZKRGDj$CiPOru!8^4yb zWRn@q?3<4@}5Ni>c`H~KWIe4_^xMC ze!A~qavsOF|HKgJ8H+Fe`U`D#2I;%waDG6KHuVIZ=_jRw3-&6l7TRH1%Z;F7hzSj%oVe=RRAL<{BVrN+p~cbpoW?> z%j!BeYs%{Y*Q!22pbL2~fg#m278qtpryIZ4PzumULWJv#=*^UceDADD|6vJs%|2Z- z!GIDDlCPU^r{IsN!N9Ao903cp0uf;Q_?jk};;hRQa8)=Yw^m}p1O$x(;%*f&X0?J@_@mgr(co$&fg zPepUPdZ-eQOk|pxXff{QM)no2-xJ?MMB#G~0K+4-h=CmhX`(Vb1b|Ukqe$;W6@+Lm zqL*`9=bR0ni>9!8z6S(){3nk4PXJ&RElX#AbBtSN;}7YWX*CN1qw3NtsEUD1j|p9- zTBf(Vm~qz(oisifR=m~h>2t0&mhW?)e}xu0^{Ut0_Q^dkEMRxc zc8<5&%UxqM(IsX`n4H}TSf?FbY25SO>Yb;mg3UJ>eKoi``1?bsTJt!$2Zgnht9x{Q zSAu)FC$h0lCiTH3+dx@oN8Z?=z>#D)amwZBz+}=EJ{WUssNbx7S*w&HLVslAa`H@4 z1(9V?#U?)}_H^fWzEnZ2C~8m4V#7-r9#`HW(Fj-&6;;Iiwh)?VD%Cud!7Os>viZUI zL0EQuC(bU1eBUIt*RVznJ&qRhn+==BTBQ|gs)ai;c={l-=6J_JeAHYwm1+mf#T(Y~ zRahX6p6)q7Q=13#Ii;zj5Vj1aTMB?|A6c)&VJgr;ShQZ~%vUM#^fWSNy$-7FJSOfx0?_3b_as3tq#*56ix7%A5@ApEg_({##)z)49>o8GcTxe(| zznl7MblCSk_KBCa!QSim<98nB-Yk}d&1Fz=1==}(JupBg($LyIhO0B?!7D_rkIARN>8j5mN zfxSoFwjUm;?ZRbKRY+P~^(U9c%FemS_-uY}q{q-}uvKGaw#g&Q;|{^I<1p%WF+F4V zo&OkvKk(JX%f1Vy&|SLJnUL{@U#CK9p|Rz^Zjn>^pl8n zFc_ZC`V=;5f!JCXBgm{CRnzossnw?ss~xxN=^ikTs5&pYs+(JMsP{=Ems14t116UW z-O1~V+o3L1eOM5vNSBs1Q^F3ZQdVb6IZzD_){-}1{*YsTeg2={ByTVLP3>4iCpu}C zQz#3BIN-IhzrEW4M7m71x|IdmGZ*TiclQ3;WDDZk&Urd~pGLjr{LB1jsk4zvnR}+)edl1D0^}4rdnUie0EfYtGUxx$OxP zd^{V#A*iDu?!H{EI334zay6rHEG0o$VDnLR&>X5)_2{=PO${O~KkT+V3|Qu70s zO~t3EKO{)uhv*Al>)&~9&ZEev)@A^fN)bd^T1^ zw)~dy5e4so2%v0AoQ;$>Q7Z&YQLlwZ$EmUqO{=>gm@-fwnU>)NmV z+M{F-406w;R#K0gzjv5>+1uZ68Zix`8IVO*($`1*Ff3n4YgFyh-;Y~PTG0f$HWUx? z)Q;^;9KeQ)*NvLB0ALb3%`l0%fay!bNtIHmMQj0>XUH*DJJTWF$KL*By+7Y%xt$q2 zwlV*@3K;;}ajaG9G!3pCx@a=>79c})3&H(vHv4*5R6Z_cv}CPo69RPsFl z=sCLo;m?k>yR@3hIfnzNA4@4xDp9muQz_ND-@%ULRMw-dS_?+q)lMgJu|>LZq|xAm zPtP;vu34b)hnw}qA^^+kx;A~>!Ro;!r}&}&pS}Gd@6#Jky`noJqUjT>Pan0I0f5QU zB4iXz=&S{RL)>SWse6#ZAWux4U1yP)KSis>)tJoWg-(=0^jO4gtq8BRKw@%MT>|Cg zE&u>+WoEbGrN8f9?zKVL6ELC$U}9$FIegL#)!xe$Csk^8e=p%_Bkw#Cr zd^Yh@7yw(p^zfrNr8gvh3LbzDsz+U=lzBNKlg17kd0{@d9ox|g1DU%v?_YWTs?b_6 zDx^`@j|mD@jhr3!>bvknpvGbIR9R$7-SSW3-b!V4sqThZFL2++5 zQ_3nn3$kjQdsUO?0K2@Kb2WlBHr5YOblT|<_uYY}We6w~uk(u-0Q}}Mj!73{$7XuH zFUbL*z8mZASIh$7@3DCH5wNhp`e??s5+?#W=G|wJLYMKr?d|{BN~cox%nNJVeERVh z`T6F^O3URBbXblxx9f}B6|Uuc7>{u(s48tEP&XybibLR))5%O3W=Sz@#w=|(0FHGn zlCIPxUr%A0&b>v%+t-Mkzvq`{9I~5c+JeJ|y_kQP9;Bf;f9rBdWj+30p0qk60(Ecv zPp9eL^)`Uh6U-Nq*QH?4sE=KMoCW5u-s3DIISfEK0 zQA(c|SU;k#q#3&GC;&R7hfg9J8UT_caqe;R-faU|;3s!pEnX5iDcs-|v7-^dEq>B1 zcNe_Xn*qz1(SMCZz#7AGK=jCZ?7fL*=ZdA z+jt#Fc8L=WEbRb*|5Bz~i()BR&$MuuykEpjT8wB7n1YhpwQE1jPh&-{W@Bola{q+7 z{l+FD&Z2)SKsVOKOC8h|hZBv3FhRqlvUd`swj?^8h35JQxeH2vdQoR_$3Xy4KUOZW z8xMbFh#~!tHq#H5ZzXCn2a3opmPJkAhiDgCp;ND1EC$xVM~RwKrOabjhq2_OA`PCT zsc|kDb+x7zsJOpfZ1nN$go>42qkss5jY1q?eP+25!7@+AX-xu`gLZzd7OIo4DfFri z#s>g;=k6grwV`bQx)|a4&-iVwCSrBBP?-jx&s?X>M9 zIx>3hr4>BS*+3Txd9MA_pDU=!Lz##Tf-jbpNYPvCki^aS&71EBiu9Wp8 z%`CNE@r>Z5&GV4ckF<-l0URJx1m{CFCNo5CD)W9X)kR+54a8;7-;Yum&)|BG0SQ>5 z3)by=U5_VT0YIfDji@G^u%jvhBqeOdokTB%5TuQLwSWI2X#x_*P2p~ zRe)l(op`GO^WSQ*5m(C2BdXe6F(v&wMDcP5bj()LCJPGlGg+O$HBI!ROI7HHriJ>W z6{5Jgiv`Lz)jdBC$n`xAL!_15wkIA=^crKJ7_z6(HMo&-noBsj1EMkhNNS~WXmaxO zYNnz~il$Pw>|E0o2UAttBU?%_DY0UiMi|0Uo85*eSfarG$1c{Dvac?1jtZg~wwI@o zd4-(co!nH^6^R7M1o;t0>Wdjp{-jDB4G#Y2I3DnqBTby=Vl0^>BOa zqmMGyxvam^N#KI1e0fLZiHXgdP6eQm&@EH{E|Ynv@U5yfLTABo&2D zH^fRI?rOTYkihS&rC2HF9V0(i`$fB0#AP`E*UvX+o%2z6E6Slk4n8T{u!U>CO7r zr~rUWt?6y5%2U61P?!P$%vqm3J}uD5g$4kG4EisfXLsMYW)D1`)GNnteJtVd!&C$kssqFOlP1++ z%4@v--g#0?`Kns)+-*!lD3>e%@K+~Kq>KcXID`Ls_))qs4ZsI4cejUcMmVjD&*8i1 zF(3+Hql!Vym82P?udeA#z~dscxvQ@abL8>WD}lKn4gP(`76bw#gj^B;{iZBVcu1` z6}8rLO9Y(UeNe~ni3V78<+3N}r&fGoryQVSc)nT(Jbk^kJ{U$ctX@$udmDfBS3AtT zH|l&xVn{UgSKqumvUbVgD02EvHt*Kn4^8NYt@@(5e8kMrsm9Ff`z(+Dy<4sz5)*)! zKHv8jFy8TarSlb_mppL&XnJzZldg%xxgrW+9@Z4In7EdZd-@405-077t1IQBM)`C_ zPB~X%ok^mU0A+6H_jtMOOud-HdRf7JqQp0pp-Wb}`Ave9le)fptXdWVfD9gNr|3Dg zv^vcR5QTG^uJGY5ek{S5!*}h0sU{M(A6ChCnP&%&?7`muA$29u4qU8d-^KN<(9MXw z8hO7doON9IFAKZvSUneSfUPC9Cy(lU`IIYo3%7H+K$@2hUv%C1)Fus6^97 z%%iQAGRFWD{qxQ#m1rQ@A>+`UJnuL~K4RZiJ4BmV4X9Pi(wta0x?bCW#eiXKwZGvI z?}LHJ$=&#&ILHbEe#uz+PDHHMJxhH6{A^jIQ=q~Kt~P49m1uGm79Zc1y0rRice&d( zo1_zrsWjKcpQZ;uKI!Ers3NmPJ>M(E80)Vk#aKP@>7Uy%#|WVa$3H_Y25^4&&Bz~S zKZdcbd};6Z(D!Bmv|n)Sv#7 z-sA%fE%Mn6sjtZOt=n6{poGoht30crRkNv{0N4O|=VVEbK>$FzcrRUM@j)X1j5u)} z=3eR5l#RR6$o%V3LmoM!uD);&2>|P<33`2_Se7Wx63RHaYsr`dFQ!7WCy*eXcXem{ zDNAaBUtjkV?EustXr@Wsv*rv#mw)N+|9%)mLi(J?$grAL%dkDa*UdB&30FD5I!G}G zU@Klgq_>2L`NU4&tuvXA+K6FnT{4G!-y32O#q3b;BSXB|w2c%8*-~As^m%yz)Elqy z7WC2}GPLH{s~?L7z@KB+@g9j4kGi5oHmT_RR+zSfzu&h70QC>|-j*z1$OZQg=NvOK z`NQiLb=YN@r7vz|&xl>iN#DM0Cwl)ho@t(ITH$ zUk0#*hw(q1!c5Z?{1t~f)S3L%J$8J|Gk`arQb#fbCA_@^>14A*j9R;$C+sg)zXpZL>6j?;1`pO1mH~QKQr`L&El<>Kc z@#v`?1H&*-k;|8SSN|M?S{2Qx*TQjA`1|aXXEji%LesYTOw26JI(#-Pm_J3Ul|3|t zXtSTU{P^A&HJE=oX`<|c!%{sDt3?*+>AiWHf4s8d`)QLdzN1SP10RGaHs8~PcFws` z)5SkNL%1TIj-7Q`hAR%jaJ@6c$W}CMbc?lODOv<%JaCeREizhLC7mdO)nvx0l>7}F z(Y%-DX01h1vwr9-B3piX?12ET6=Vl!D z;4n~*LQ%4A+X~0!fr54)U8BR?8*ymOtfE+5OKZ=oxa`$Q#W{;%hqph2W-ChoJ?3(* z?y)eKeB>F{TC*d~yJJR@)anGrz&~E+>44_M6~Rases8p;dXT)1=o6Uz1**lI-?iim zZBw*UzQJ5PRW?+%6ZU}Pr=m8C87mmBZ!rZxdTgoAo%ebI5Im-#DrrU2bd~v3KSr;? zfIZRPX%7r1ro-K9e1`~mTAH>h_30^bRU745t?S}0Z)3Dw?$th8*`pr$udul*%@^5L zB{(6Ap(Y(LzegLsYd!e@Ss*Bp-u0OffKej7eUkJxdDit`T53WgfsZ1J-qne52ZX8KLH#L5GMMX>B&P5QIu<>@DQ zOlsX#$<-FTWue!nx?VdV1A`x_5=O{J$(;w2Dp)+w;f$T*sCG1MveWSDfc>DuqmCD* zn9%$O&phfpQhtF2cy>9RN=*z~ajB{1|8s#s3kD=D6-{%;0J>8)N5UkVre3koAV3?= z?)L649(TWba)8=OrkXI(mTqOqPW>VS4EKztb2H>54IQ1UMmz18;toKIaAge*Kr;dJ zhsijvP_L||7|@2jEfQ{lxkA|lM|aN44^ZrK2>A0ecWL*09Gjc5R;ND{&Mg1UoUq&|A++68ls4T*NXvj zM9i$zkO1tefVmPSjn4oBF-G1*@@6dRh}HmFjeDz14Lyj!{Kd?t?hu`);9%Gg~K9`V6Ko=ebHG8FLm$kVldh z=i$NNYDxZ*V8MsQ-CG{iroiChuzwK@#9{OHXP980aOoDu&%XNfvkSax-5Cg43IN@_ z^@(HUr--6<-pf(M>QM(V2h$I%t;bps7U!PKFA*i4DmpviVinVfe6Vz@w;EH`>Hb2L zY7rEC&PE*odtg4S_47r`1!LrG>ZZ`W+y&MrEl;~rW2k?Rx&QjZ^&;e@GOBZr@mD&b z@>tvG(yMf1>4+(jDv@IZBenp5;egK81Jt~zcWd-R@7lTHjEn&BbthmMQg_c~ow2%S zT5VNRcZ_QpAjMYO6e~+mw;xMRK`=cS0HJgNjibh3PhhsacV=L zZ#&Dlm1JYiO%}ehKU~_!jfnT%B51Jz!3I{Gwm^-nW1!S#uAxM=T}3yyRGK77@zpg8 z#=2)l0^1Lag+SY;bWw{Z0N{WBNMm$Ks+w1Sz;xqQvWq{)5;)0PnbIGn#iR{WbeYHA z|NpGxFaC#;4uSa^}`+7HE=Vb=GjXzy%vB1o+yf z*;n=2MAVxr(n&=%AaA$bO|PhW4^Fa(#To}xpQ~Oc$9wGamJ=8hQ=f3z4yiP$M!{Qs zEh{?`Ru3ga&7}$O*pL?{%}{MONx?+w+~bK_ed72^n9qb`AK-8=@3ojRtwhOl4V<&6 z67^WHDyVxcLQc7pwlu-aBV|=x5~z|9(o?Lne<00L8A&qB$(vSBu5^ER4hdKW&Bcf$ zkCjcDEj(BCL1m1QMFJHXfc3%TT|LE09L4KSo=gaNW73Y?tG%PDf`ceUh54PaVBS^b>^aWK5dth*WLG{f$$_NizWx7(gn8#2LsU%2*>#JzQ4^(xfvQR)lJ?KP7VqcfS zRF{gU0`LRSRJd)p7)lf!NW%AQ!5@HTLORpep1DTiQ6CdQ!CTa)wA;Umj<7eW2Bd^L zHWtl8&L*PW%9$L|fp)~7z$VZK-Q`vGdo?(>sVUTyaJkRZR!%^I>|U&S0cb|Vo_-{u z?+*-yXt|h;=4QsTeniY2&G{QXdLu9#%M#rrMq~rb&?~Rls=g)u`RBa)sE!HJ9Kguz zLXT`spRoeau10m>pUy#kyj@VT!`Dsq%>1GDC0m0~E@ET-2_Gb$(@bf<}^&xyej&4Csg|m&DZu0LUkkUG{$+ z7}W0BMHM=Eg&|bndij*<$5ClCqWU#7A%b4-S#8X5p{f8?)2j*m&@45Br9OSKv??Kk z&)rBVcN}AtNp^G3U^1(%bF3-~FyTt;c-jB}ZMsXh3i5TzCR7y>AfI)&6*&xe*8fme zDz9;ju)5hEl<)hSL0Vi+h9Ot#_P=u*!VGMpXQk;Y7yT|+DYJ9~!t(>@%dy_|Qtt-< z_gHk&&dc?eX?D#EDwVBUBvUEW_FFN~an3G{dDw5NW^G*Da`yEcE^G^uzL{ZF?h&)} zU>3@%N<__C5F9+8qfQCAuG1Nhg8*RT7+LY@Ys`Z932P)*tk8CA1jU9F#eb^}b-7mZ z#Rt~Q-PYQOy^gJ09gIH#r`#2lffyQq4odcrD&-CD{1~04Kx7{{ajx?)tU%zh+`?*% zUER$sFWwQbx~cUNZR?i4U|@}a#Q3A?mT-^@hC{KKNef1?vNA>{R+x^hE9}+Fdja5C zBji(UFIA2)9Mg>;w2KA+@0dw67q%rcy5G(zRWJ8Y6oE~cMjD#7m2T!%*Ex0%?3|6F z9Db*X5U0NLVMMOfv`#tst{K2pmM;6iYqU-;u~d`A4*lMM%Uor{b=uZl;~0U81ORNK z={hI+p6>5ppaYN#nkwZEi$_nt2ZPZGOC-upxYTE9&|NCewc7O~U!+Bt%wrGCimg4f z0sHDp$Gvxl>!Nz!-%zQRu7X@JN*rG4F&J$9(-$nJk?X7%^~hk* zHlFefS^#XdeD>9k!@%yFUbS+RSFkwGf8r>NY-LcNYbJ*hy1kaM0ibtpnN*t);<0Q$ zerpG1+b!E806^Z^b(T^CfKxVBZvD_zfj`5PH_8LBzHSZ}Wz?0oQVgQXV8C4mDZ>wq zW8J#R)u!Y0S+w{P`Jx%KRMXIf2C-dD)#ixvj7kMbwA~Ueq_*mP@T;xZ>~SMqq%s|L z_Dy<{@M_Q6-QMi6RnU{PtK%HTnHauGIWwef3EHtJWhLtjpE5DDs(yavA_JHhDLvNL zbreXGd&vUBn9YTTT$6N0e@y-n9t0Xoh<>cfuFN!N84Dd5lje!*WSLPFOqL$JJm58W zLUb)Hl4SnBrYEmkqDdmlO+qG#!3e-1J9^W-Mdee}8G$E8NVO&inDZ#28=LG|p-yU(cFsHE zfeD-^j;JQ?C%b1D(!t3s>yO;(J`+C@hlsnG06DCLOj}SrSMp+^(>~>b=2?A`CgG7=ZRp@8E}E;B4Ko z4^u9R3XM-mV*uktf~UTV8USDif4K+%*7~Nyrkasd5PVU}$1K!E`Yl)a&|%WWF1n=e zYz){-36^~n1i-mt0_URw0ASvC39p)l!_#nIeLV~m^I`5&4WJG{0%iBK zh^OdHqSv7Y@+k7tc6WJa&jIA2@AnBwGq7r`Os9k|gAg^_+CB>*D%|y} ze|4Hr&5!@(cj$}8fV#fzn$cA7%-v^*vFi~dN!EFpC7V};7)7JZ7KsVfZt z?2Rs7{B>iBf_g7I{31jZf03g$jiK)8IL1HtMymn#LNCyR7#?To@#bxpYg&6&767o# z?KRyeyy{paFbF`#R+;+~&wsxQnPB0pmV6@!Cy%fHbnry>NQunN#xXkz0n2wsxd_xuJBy73Hf}Oxj6t} zw>av6QZAhOMLY(;XJ24b3;^m`zPd3$HTJRI?=Df)zQ?37P+cs8`ZntoYWRK>n#x&@-1$~|n?;=!Maw_6TCx022kGR_+PL?dz} zhj=gjyy@pSJoH_Hi3nF^oF(17cZGaNNPPnPUgA_?m)n!B7xt##8L7mZ-j!jF_&ZQ( z1wS$Cl#W&H8pPj~$JuYAjpFXb8Dl}93v*ktHEkN$G)cAW_GAPr?wevo`#RI-v}>4l zk!wB`a@FsaDBuz$NqWKYR+EE@Av;5s*ak1VFWVe|D8U|<=sq|&hQJF$20L4!bM{q( z2B6bWXqnD_y)?DWY>Td4xk$QWeDHkn;9R>eM)YEmbui_*Z?3)fy#=$|tI#xU=_f1L zpLm6rH^twQ!nxs4>gZ70ACdMap8Q+&n>OOgVr6UWwTDDAB!wS@(nSuZzuS+5VR?YM zoc}m-F)rRCH{~h+zMr*gv;aMgdFf$r;zJC>=3T(;kb7TrNR~u0ZfeoTUwf(0IiqNb zL9q7es<-P89p`pMb)y~#BXIpaJWneCFs(J$(wHI)#>D9ztt~kWM$1zlm(1*BmKYI& zM0_;>AjCi!7_TM7!Le2{ElUcW7#bq&a(S7oG9vylZK(z!o){pjb;g=oVo@29l{Z7! z5)ooRB0d_6HIZqJIT`^K35_YHPnZ#F%ZWUM@Z>nvmgX|8h@AyPi}Zl43N25QYC#B8GzWc#WZnl9I2X^FYk=QV?>An(Ug}nq^uNU ziOKyS(~=X(v1U9+Q4C;3RG-z_nKPJX2s5-KmV_Lr zlZK_5P&H$U)?mmjS=A|r)HasOj5Ja!!DG@CKRgoEOLmnJCd7g*5mj(98M(t5nVlAq zCd9GYsubPGFOA3Ruy-?MZ zwk73NCgTwRHCG(kL}o^AQ|c6&^B4dq>!>Do6*+A(ElY}l)mAmJ#N+(uu50%L9d_FG z>99QX6Hm{C^k`BK@ITRm>MEZK`UiXjol>z_ANzD;dKRZB9=C=K9$>L>;Ykqj>0^(5 zO6UC4a)U(?a(mtQK9k&`_H{~oXMXG>}h_mdblhw55jp?;rm68DJ4qsUi~z=cqE4gHuw&c zDWg=E5HWIp%!x;Ih4smQki};%!;Ew$ZEn`e~L2`RI6E~O6k|<8`|H510iXac4 z(W0dIVAOEj=ox!l{g?&RpSaQb%Pgy}o=@vIU#93@{Ra;(ru0n7je_J_$KCIGhP_Sx zdDqeE;d9*d$4mJr2wt8)T(V7buOe#mmskB$Wkh-1Zkbnj^1T8LW7?jSQxvXStrmT7tuN5`9t#b*;Q=ASroapz$!#f@jQoAJhyl8?)} zk+bJbe4Bh`7wR(RD#zHDhL`u_nx|J&pqB^oOSj$Tb>mme& z0vlD8g^xnloma0k|A(h*kx|KXkX(2`5@Y@M0|vx7ohxhMv)G`~v}f{m%bBzt4QYD-49}{7*pNd3#@1Mt*Dy7RyXk>qZXy^?inv3+i`$%KZrR+l9~HK z0HEx89ZPBkkAx(O3EBFBCyP|o8@lfY`Ti2Xxlt(oI`73?om}E!5@C5cOoZqNCd|6D zSAZQY3o?4%Zqs{8d^tdEJbTD`DOo3&yct7R#f*(JDzr?mmRj~_HeB;LHx@1^;sxEH zy1txeCn-GbyiWWs!$*_LW8IZvbS>Jxi(zdVUV6l2NP<)WwQMi>l+JloP2VH^Os*f~ z+@%=xS-I{mD9YppNKI_F>W=W$iA_U z^`5Z4X#MJ#<%d3rh&DVfJ9`W$T%GmGzFN}>=LG~!-RcPmpujqLb{x%h0E&EZ{QkX@ z{$uo2wQP5p!ks(%y9FkANL>k zANL>kANL>kANL>kUlH}-clH3j!4-Qz9$O~agJnY8$R5PC*$ie6N&6qQa>gCN&)!jN z53-9%?f_38iE4z1Kh=-SLHv)dS{MP6^s&BY4wlFK@>5+F!!gVp9OJIosv1=cbMO_f zB_ou0nK!_DMp&)#=|CI9v-q}ajS)zw8cE|&#oDM4Q?iFMzR%u)`SKwVf=p zwgptyw|qh3CPu04MN)}Z*~0UkcJ*s(d`1;(U^IOU+TF3(_lO^&_}FKNw!LC%pNt?b zT_o060z5D2z0jT+;rvV$Ho!YS0B_=zq!Sl9Ae*9uIB|!>`YAPRzs@EbRn*eW)nOR{ r^FL-i#cnveOaSfh0yv+HY|y1cS>&_GW#P%Aolh&DW>^0B(GCg#ByvDr literal 0 HcmV?d00001 From ea52496f2fadc192858442c07f7a39863324a64c Mon Sep 17 00:00:00 2001 From: Yoseph Kurnia Soenggoro Date: Mon, 17 Jul 2023 19:44:45 +0700 Subject: [PATCH 3/3] add sample erc6551 query --- pages/advanced/indexing-erc6551.mdx | 62 ++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/pages/advanced/indexing-erc6551.mdx b/pages/advanced/indexing-erc6551.mdx index e8b4e6d..15e8b30 100644 --- a/pages/advanced/indexing-erc6551.mdx +++ b/pages/advanced/indexing-erc6551.mdx @@ -65,7 +65,36 @@ import { init, useQuery } from "@airstack/airstack-react"; // Initialize the React SDK init("YOUR_AIRSTACK_API_KEY"); -const query = `YOUR_QUERY`; +const query = ` +query MyQuery { + Accounts( + input: { + filter: { + tokenAddress: { _eq: "0x26727ed4f5ba61d3772d1575bca011ae3aef5d36" } + tokenId: { _eq: "0" } + } + blockchain: ethereum + limit: 50 + } + ) { + Account { + address { + addresses + } + implementation + registry + salt + standard + updatedAtBlockNumber + updatedAtBlockTimestamp + createdAtBlockNumber + createdAtBlockTimestamp + creationTransactionHash + deployer + } + } +} +`; const Component = () => { const { data, loading, error } = useQuery(query, {}, { cache: false }); @@ -91,7 +120,36 @@ from airstack.execute_query import AirstackClient api_client = AirstackClient(api_key='YOUR_AIRSTACK_API_KEY') -query = "YOUR_QUERY" +query = """ +query MyQuery { + Accounts( + input: { + filter: { + tokenAddress: { _eq: "0x26727ed4f5ba61d3772d1575bca011ae3aef5d36" } + tokenId: { _eq: "0" } + } + blockchain: ethereum + limit: 50 + } + ) { + Account { + address { + addresses + } + implementation + registry + salt + standard + updatedAtBlockNumber + updatedAtBlockTimestamp + createdAtBlockNumber + createdAtBlockTimestamp + creationTransactionHash + deployer + } + } +} +""" async def main(): execute_query_client = api_client.create_execute_query_object(