From e3df3c2bed4174de20d9bad0a0cbff2eab3ed3da Mon Sep 17 00:00:00 2001 From: iskysun96 Date: Mon, 27 May 2024 15:39:39 +0900 Subject: [PATCH] reorg --- .../NftMarketplace.approval.teal | 48 +- .../nft_marketplace/NftMarketplace.arc32.json | 2 +- .../artifacts/nft_marketplace/client.ts | 2 +- .../nft_marketplace/contract.py | 7 +- .../nft_marketplace/deploy-config.ts | 556 +++++------------- .../nft_marketplace_list/deploy-config.ts | 25 +- .../src/components/Buy.tsx | 11 +- .../src/components/Header.tsx | 18 +- .../src/components/MintNft.tsx | 3 +- .../src/components/NftCardSection.tsx | 14 +- .../src/components/Sell.tsx | 11 +- .../src/components/Withdraw.tsx | 13 +- .../src/contracts/NftMarketplace.ts | 2 +- .../src/methods.ts | 162 +++-- .../src/utils/getCurrentNftmClient.ts | 49 ++ .../src/utils/marketplaceListAppId.ts | 2 +- 16 files changed, 383 insertions(+), 542 deletions(-) create mode 100644 projects/orakle-nft-marketplace-app-frontend/src/utils/getCurrentNftmClient.ts diff --git a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/NftMarketplace.approval.teal b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/NftMarketplace.approval.teal index 147d3f0..8dfe66b 100644 --- a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/NftMarketplace.approval.teal +++ b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/NftMarketplace.approval.teal @@ -73,7 +73,7 @@ main_buy_route@5: return main_withdraw_and_delete_route@6: - // smart_contracts/nft_marketplace/contract.py:177 + // smart_contracts/nft_marketplace/contract.py:176 // @arc4.abimethod(allow_actions=["DeleteApplication"]) txn OnCompletion int DeleteApplication @@ -241,37 +241,31 @@ buy: * == assert - // smart_contracts/nft_marketplace/contract.py:139 - // assert Txn.sender != Global.creator_address - txn Sender - global CreatorAddress - != - assert - // smart_contracts/nft_marketplace/contract.py:141-145 + // smart_contracts/nft_marketplace/contract.py:140-144 // itxn.AssetTransfer( // xfer_asset=self.asset_id, // asset_receiver=Txn.sender, // asset_amount=quantity, // ).submit() itxn_begin - // smart_contracts/nft_marketplace/contract.py:142 + // smart_contracts/nft_marketplace/contract.py:141 // xfer_asset=self.asset_id, int 0 byte "asset_id" app_global_get_ex assert // check asset_id exists - // smart_contracts/nft_marketplace/contract.py:143 + // smart_contracts/nft_marketplace/contract.py:142 // asset_receiver=Txn.sender, txn Sender frame_dig -1 itxn_field AssetAmount itxn_field AssetReceiver itxn_field XferAsset - // smart_contracts/nft_marketplace/contract.py:141 + // smart_contracts/nft_marketplace/contract.py:140 // itxn.AssetTransfer( int axfer itxn_field TypeEnum - // smart_contracts/nft_marketplace/contract.py:141-145 + // smart_contracts/nft_marketplace/contract.py:140-144 // itxn.AssetTransfer( // xfer_asset=self.asset_id, // asset_receiver=Txn.sender, @@ -283,79 +277,79 @@ buy: // smart_contracts.nft_marketplace.contract.NftMarketplace.withdraw_and_delete() -> uint64: withdraw_and_delete: - // smart_contracts/nft_marketplace/contract.py:177-178 + // smart_contracts/nft_marketplace/contract.py:176-177 // @arc4.abimethod(allow_actions=["DeleteApplication"]) // def withdraw_and_delete(self) -> UInt64: proto 0 1 - // smart_contracts/nft_marketplace/contract.py:179 + // smart_contracts/nft_marketplace/contract.py:178 // assert Txn.sender == Global.creator_address txn Sender global CreatorAddress == assert - // smart_contracts/nft_marketplace/contract.py:180 + // smart_contracts/nft_marketplace/contract.py:179 // contract_balance = Global.current_application_address.balance global CurrentApplicationAddress acct_params_get AcctBalance assert // account funded - // smart_contracts/nft_marketplace/contract.py:182-186 + // smart_contracts/nft_marketplace/contract.py:181-185 // itxn.AssetTransfer( // xfer_asset=self.asset_id, // asset_receiver=Global.creator_address, // asset_close_to=Global.creator_address, // ).submit() itxn_begin - // smart_contracts/nft_marketplace/contract.py:183 + // smart_contracts/nft_marketplace/contract.py:182 // xfer_asset=self.asset_id, int 0 byte "asset_id" app_global_get_ex assert // check asset_id exists - // smart_contracts/nft_marketplace/contract.py:184 + // smart_contracts/nft_marketplace/contract.py:183 // asset_receiver=Global.creator_address, global CreatorAddress - // smart_contracts/nft_marketplace/contract.py:185 + // smart_contracts/nft_marketplace/contract.py:184 // asset_close_to=Global.creator_address, dup itxn_field AssetCloseTo itxn_field AssetReceiver itxn_field XferAsset - // smart_contracts/nft_marketplace/contract.py:182 + // smart_contracts/nft_marketplace/contract.py:181 // itxn.AssetTransfer( int axfer itxn_field TypeEnum - // smart_contracts/nft_marketplace/contract.py:182-186 + // smart_contracts/nft_marketplace/contract.py:181-185 // itxn.AssetTransfer( // xfer_asset=self.asset_id, // asset_receiver=Global.creator_address, // asset_close_to=Global.creator_address, // ).submit() itxn_submit - // smart_contracts/nft_marketplace/contract.py:188-191 + // smart_contracts/nft_marketplace/contract.py:187-190 // itxn.Payment( // receiver=Global.creator_address, // close_remainder_to=Global.creator_address, // ).submit() itxn_begin - // smart_contracts/nft_marketplace/contract.py:189 + // smart_contracts/nft_marketplace/contract.py:188 // receiver=Global.creator_address, global CreatorAddress - // smart_contracts/nft_marketplace/contract.py:190 + // smart_contracts/nft_marketplace/contract.py:189 // close_remainder_to=Global.creator_address, dup itxn_field CloseRemainderTo itxn_field Receiver - // smart_contracts/nft_marketplace/contract.py:188 + // smart_contracts/nft_marketplace/contract.py:187 // itxn.Payment( int pay itxn_field TypeEnum - // smart_contracts/nft_marketplace/contract.py:188-191 + // smart_contracts/nft_marketplace/contract.py:187-190 // itxn.Payment( // receiver=Global.creator_address, // close_remainder_to=Global.creator_address, // ).submit() itxn_submit - // smart_contracts/nft_marketplace/contract.py:193 + // smart_contracts/nft_marketplace/contract.py:192 // return contract_balance retsub diff --git a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/NftMarketplace.arc32.json b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/NftMarketplace.arc32.json index 7b7ff96..6cac92e 100644 --- a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/NftMarketplace.arc32.json +++ b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/NftMarketplace.arc32.json @@ -17,7 +17,7 @@ } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MzAKICAgIC8vIGNsYXNzIE5mdE1hcmtldHBsYWNlKGFyYzQuQVJDNENvbnRyYWN0KToKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBtYWluX2JhcmVfcm91dGluZ0A5CiAgICBtZXRob2QgImJvb3RzdHJhcChhc3NldCx1aW50NjQscGF5KXZvaWQiCiAgICBtZXRob2QgImJ1eShwYXksdWludDY0KXZvaWQiCiAgICBtZXRob2QgIndpdGhkcmF3X2FuZF9kZWxldGUoKXVpbnQ2NCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIG1haW5fYm9vdHN0cmFwX3JvdXRlQDQgbWFpbl9idXlfcm91dGVANSBtYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANgogICAgZXJyIC8vIHJlamVjdCB0cmFuc2FjdGlvbgoKbWFpbl9ib290c3RyYXBfcm91dGVANDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQXNzZXRzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBidG9pCiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgY2FsbHN1YiBib290c3RyYXAKICAgIGludCAxCiAgICByZXR1cm4KCm1haW5fYnV5X3JvdXRlQDU6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjEyOQogICAgLy8gQGFyYzQuYWJpbWV0aG9kCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBjbGFzcyBOZnRNYXJrZXRwbGFjZShhcmM0LkFSQzRDb250cmFjdCk6CiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGJ0b2kKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTI5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIGNhbGxzdWIgYnV5CiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc3CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBpbnQgRGVsZXRlQXBwbGljYXRpb24KICAgID09CiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIERlbGV0ZUFwcGxpY2F0aW9uCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiB3aXRoZHJhd19hbmRfZGVsZXRlCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX2JhcmVfcm91dGluZ0A5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIHJlamVjdCB0cmFuc2FjdGlvbgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5uZnRfbWFya2V0cGxhY2UuY29udHJhY3QuTmZ0TWFya2V0cGxhY2UuYm9vdHN0cmFwKGFzc2V0OiB1aW50NjQsIHVuaXRhcnlfcHJpY2U6IHVpbnQ2NCwgbWJyX3BheTogdWludDY0KSAtPiB2b2lkOgpib290c3RyYXA6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojg2LTg5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBib290c3RyYXAoCiAgICAvLyAgICAgc2VsZiwgYXNzZXQ6IEFzc2V0LCB1bml0YXJ5X3ByaWNlOiBVSW50NjQsIG1icl9wYXk6IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAzIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTAKICAgIC8vIGFzc2VydCBUeG4uc2VuZGVyID09IEdsb2JhbC5jcmVhdG9yX2FkZHJlc3MKICAgIHR4biBTZW5kZXIKICAgIGdsb2JhbCBDcmVhdG9yQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5MQogICAgLy8gYXNzZXJ0IG5vdCBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLmlzX29wdGVkX2luKEFzc2V0KHNlbGYuYXNzZXRfaWQpKQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGludCAwCiAgICBieXRlICJhc3NldF9pZCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgYXNzZXRfaWQgZXhpc3RzCiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgIQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjkzCiAgICAvLyBhc3NlcnQgbWJyX3BheS5yZWNlaXZlciA9PSBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzCiAgICBmcmFtZV9kaWcgLTEKICAgIGd0eG5zIFJlY2VpdmVyCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5NAogICAgLy8gYXNzZXJ0IG1icl9wYXkuYW1vdW50ID09IEdsb2JhbC5taW5fYmFsYW5jZSArIEdsb2JhbC5hc3NldF9vcHRfaW5fbWluX2JhbGFuY2UKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBnbG9iYWwgTWluQmFsYW5jZQogICAgZ2xvYmFsIEFzc2V0T3B0SW5NaW5CYWxhbmNlCiAgICArCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk1CiAgICAvLyBhc3NlcnQgbm90IHNlbGYuYm9vdHN0cmFwcGVkCiAgICBpbnQgMAogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBib290c3RyYXBwZWQgZXhpc3RzCiAgICAhCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTcKICAgIC8vIHNlbGYuYXNzZXRfaWQgPSBhc3NldC5pZAogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBmcmFtZV9kaWcgLTMKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk4CiAgICAvLyBzZWxmLnVuaXRhcnlfcHJpY2UgPSB1bml0YXJ5X3ByaWNlCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgZnJhbWVfZGlnIC0yCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5OQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBUcnVlCiAgICBieXRlICJib290c3RyYXBwZWQiCiAgICBpbnQgMQogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLAogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTA0CiAgICAvLyBhc3NldF9hbW91bnQ9MCwKICAgIGludCAwCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGZyYW1lX2RpZyAtMwogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fc3VibWl0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmJ1eShidXllcl90eG46IHVpbnQ2NCwgcXVhbnRpdHk6IHVpbnQ2NCkgLT4gdm9pZDoKYnV5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMjktMTM0CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBidXkoCiAgICAvLyAgICAgc2VsZiwKICAgIC8vICAgICBidXllcl90eG46IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uLAogICAgLy8gICAgIHF1YW50aXR5OiBVSW50NjQsCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAyIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM1CiAgICAvLyBhc3NlcnQgc2VsZi51bml0YXJ5X3ByaWNlICE9IFVJbnQ2NCgwKQogICAgaW50IDAKICAgIGJ5dGUgInVuaXRhcnlfcHJpY2UiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHVuaXRhcnlfcHJpY2UgZXhpc3RzCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM2CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLnNlbmRlciA9PSBUeG4uc2VuZGVyCiAgICBmcmFtZV9kaWcgLTIKICAgIGd0eG5zIFNlbmRlcgogICAgdHhuIFNlbmRlcgogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMzcKICAgIC8vIGFzc2VydCBidXllcl90eG4ucmVjZWl2ZXIgPT0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcwogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM4CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLmFtb3VudCA9PSBzZWxmLnVuaXRhcnlfcHJpY2UgKiBxdWFudGl0eQogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBBbW91bnQKICAgIGludCAwCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayB1bml0YXJ5X3ByaWNlIGV4aXN0cwogICAgZnJhbWVfZGlnIC0xCiAgICAqCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjEzOQogICAgLy8gYXNzZXJ0IFR4bi5zZW5kZXIgIT0gR2xvYmFsLmNyZWF0b3JfYWRkcmVzcwogICAgdHhuIFNlbmRlcgogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAhPQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MS0xNDUKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MgogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTQzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1UeG4uc2VuZGVyLAogICAgdHhuIFNlbmRlcgogICAgZnJhbWVfZGlnIC0xCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGl0eG5fZmllbGQgWGZlckFzc2V0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgaW50IGF4ZmVyCiAgICBpdHhuX2ZpZWxkIFR5cGVFbnVtCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MS0xNDUKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLm5mdF9tYXJrZXRwbGFjZS5jb250cmFjdC5OZnRNYXJrZXRwbGFjZS53aXRoZHJhd19hbmRfZGVsZXRlKCkgLT4gdWludDY0Ogp3aXRoZHJhd19hbmRfZGVsZXRlOgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxNzctMTc4CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICAvLyBkZWYgd2l0aGRyYXdfYW5kX2RlbGV0ZShzZWxmKSAtPiBVSW50NjQ6CiAgICBwcm90byAwIDEKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc5CiAgICAvLyBhc3NlcnQgVHhuLnNlbmRlciA9PSBHbG9iYWwuY3JlYXRvcl9hZGRyZXNzCiAgICB0eG4gU2VuZGVyCiAgICBnbG9iYWwgQ3JlYXRvckFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgwCiAgICAvLyBjb250cmFjdF9iYWxhbmNlID0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcy5iYWxhbmNlCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBhc3NlcnQgLy8gYWNjb3VudCBmdW5kZWQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgyLTE4NgogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4MwogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg0CiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4NQogICAgLy8gYXNzZXRfY2xvc2VfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIGR1cAogICAgaXR4bl9maWVsZCBBc3NldENsb3NlVG8KICAgIGl0eG5fZmllbGQgQXNzZXRSZWNlaXZlcgogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgyCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgyLTE4NgogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODgtMTkxCiAgICAvLyBpdHhuLlBheW1lbnQoCiAgICAvLyAgICAgcmVjZWl2ZXI9R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICAgICBjbG9zZV9yZW1haW5kZXJfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg5CiAgICAvLyByZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE5MAogICAgLy8gY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICBkdXAKICAgIGl0eG5fZmllbGQgQ2xvc2VSZW1haW5kZXJUbwogICAgaXR4bl9maWVsZCBSZWNlaXZlcgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODgKICAgIC8vIGl0eG4uUGF5bWVudCgKICAgIGludCBwYXkKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg4LTE5MQogICAgLy8gaXR4bi5QYXltZW50KAogICAgLy8gICAgIHJlY2VpdmVyPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyAgICAgY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxOTMKICAgIC8vIHJldHVybiBjb250cmFjdF9iYWxhbmNlCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLl9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjUyCiAgICAvLyBkZWYgX19pbml0X18oc2VsZikgLT4gTm9uZToKICAgIHByb3RvIDAgMAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1MwogICAgLy8gc2VsZi5hc3NldF9pZCA9IFVJbnQ2NCgwKQogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBpbnQgMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6NTQKICAgIC8vIHNlbGYudW5pdGFyeV9wcmljZSA9IFVJbnQ2NCgwKQogICAgYnl0ZSAidW5pdGFyeV9wcmljZSIKICAgIGludCAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1NQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBGYWxzZQogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgaW50IDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MzAKICAgIC8vIGNsYXNzIE5mdE1hcmtldHBsYWNlKGFyYzQuQVJDNENvbnRyYWN0KToKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBtYWluX2JhcmVfcm91dGluZ0A5CiAgICBtZXRob2QgImJvb3RzdHJhcChhc3NldCx1aW50NjQscGF5KXZvaWQiCiAgICBtZXRob2QgImJ1eShwYXksdWludDY0KXZvaWQiCiAgICBtZXRob2QgIndpdGhkcmF3X2FuZF9kZWxldGUoKXVpbnQ2NCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIG1haW5fYm9vdHN0cmFwX3JvdXRlQDQgbWFpbl9idXlfcm91dGVANSBtYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANgogICAgZXJyIC8vIHJlamVjdCB0cmFuc2FjdGlvbgoKbWFpbl9ib290c3RyYXBfcm91dGVANDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQXNzZXRzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBidG9pCiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgY2FsbHN1YiBib290c3RyYXAKICAgIGludCAxCiAgICByZXR1cm4KCm1haW5fYnV5X3JvdXRlQDU6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjEyOQogICAgLy8gQGFyYzQuYWJpbWV0aG9kCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBjbGFzcyBOZnRNYXJrZXRwbGFjZShhcmM0LkFSQzRDb250cmFjdCk6CiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGJ0b2kKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTI5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIGNhbGxzdWIgYnV5CiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc2CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBpbnQgRGVsZXRlQXBwbGljYXRpb24KICAgID09CiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIERlbGV0ZUFwcGxpY2F0aW9uCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiB3aXRoZHJhd19hbmRfZGVsZXRlCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX2JhcmVfcm91dGluZ0A5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIHJlamVjdCB0cmFuc2FjdGlvbgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5uZnRfbWFya2V0cGxhY2UuY29udHJhY3QuTmZ0TWFya2V0cGxhY2UuYm9vdHN0cmFwKGFzc2V0OiB1aW50NjQsIHVuaXRhcnlfcHJpY2U6IHVpbnQ2NCwgbWJyX3BheTogdWludDY0KSAtPiB2b2lkOgpib290c3RyYXA6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojg2LTg5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBib290c3RyYXAoCiAgICAvLyAgICAgc2VsZiwgYXNzZXQ6IEFzc2V0LCB1bml0YXJ5X3ByaWNlOiBVSW50NjQsIG1icl9wYXk6IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAzIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTAKICAgIC8vIGFzc2VydCBUeG4uc2VuZGVyID09IEdsb2JhbC5jcmVhdG9yX2FkZHJlc3MKICAgIHR4biBTZW5kZXIKICAgIGdsb2JhbCBDcmVhdG9yQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5MQogICAgLy8gYXNzZXJ0IG5vdCBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLmlzX29wdGVkX2luKEFzc2V0KHNlbGYuYXNzZXRfaWQpKQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGludCAwCiAgICBieXRlICJhc3NldF9pZCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgYXNzZXRfaWQgZXhpc3RzCiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgIQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjkzCiAgICAvLyBhc3NlcnQgbWJyX3BheS5yZWNlaXZlciA9PSBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzCiAgICBmcmFtZV9kaWcgLTEKICAgIGd0eG5zIFJlY2VpdmVyCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5NAogICAgLy8gYXNzZXJ0IG1icl9wYXkuYW1vdW50ID09IEdsb2JhbC5taW5fYmFsYW5jZSArIEdsb2JhbC5hc3NldF9vcHRfaW5fbWluX2JhbGFuY2UKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBnbG9iYWwgTWluQmFsYW5jZQogICAgZ2xvYmFsIEFzc2V0T3B0SW5NaW5CYWxhbmNlCiAgICArCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk1CiAgICAvLyBhc3NlcnQgbm90IHNlbGYuYm9vdHN0cmFwcGVkCiAgICBpbnQgMAogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBib290c3RyYXBwZWQgZXhpc3RzCiAgICAhCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTcKICAgIC8vIHNlbGYuYXNzZXRfaWQgPSBhc3NldC5pZAogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBmcmFtZV9kaWcgLTMKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk4CiAgICAvLyBzZWxmLnVuaXRhcnlfcHJpY2UgPSB1bml0YXJ5X3ByaWNlCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgZnJhbWVfZGlnIC0yCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5OQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBUcnVlCiAgICBieXRlICJib290c3RyYXBwZWQiCiAgICBpbnQgMQogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLAogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTA0CiAgICAvLyBhc3NldF9hbW91bnQ9MCwKICAgIGludCAwCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGZyYW1lX2RpZyAtMwogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fc3VibWl0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmJ1eShidXllcl90eG46IHVpbnQ2NCwgcXVhbnRpdHk6IHVpbnQ2NCkgLT4gdm9pZDoKYnV5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMjktMTM0CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBidXkoCiAgICAvLyAgICAgc2VsZiwKICAgIC8vICAgICBidXllcl90eG46IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uLAogICAgLy8gICAgIHF1YW50aXR5OiBVSW50NjQsCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAyIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM1CiAgICAvLyBhc3NlcnQgc2VsZi51bml0YXJ5X3ByaWNlICE9IFVJbnQ2NCgwKQogICAgaW50IDAKICAgIGJ5dGUgInVuaXRhcnlfcHJpY2UiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHVuaXRhcnlfcHJpY2UgZXhpc3RzCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM2CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLnNlbmRlciA9PSBUeG4uc2VuZGVyCiAgICBmcmFtZV9kaWcgLTIKICAgIGd0eG5zIFNlbmRlcgogICAgdHhuIFNlbmRlcgogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMzcKICAgIC8vIGFzc2VydCBidXllcl90eG4ucmVjZWl2ZXIgPT0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcwogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM4CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLmFtb3VudCA9PSBzZWxmLnVuaXRhcnlfcHJpY2UgKiBxdWFudGl0eQogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBBbW91bnQKICAgIGludCAwCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayB1bml0YXJ5X3ByaWNlIGV4aXN0cwogICAgZnJhbWVfZGlnIC0xCiAgICAqCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MC0xNDQKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MQogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTQyCiAgICAvLyBhc3NldF9yZWNlaXZlcj1UeG4uc2VuZGVyLAogICAgdHhuIFNlbmRlcgogICAgZnJhbWVfZGlnIC0xCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGl0eG5fZmllbGQgWGZlckFzc2V0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MAogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgaW50IGF4ZmVyCiAgICBpdHhuX2ZpZWxkIFR5cGVFbnVtCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MC0xNDQKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLm5mdF9tYXJrZXRwbGFjZS5jb250cmFjdC5OZnRNYXJrZXRwbGFjZS53aXRoZHJhd19hbmRfZGVsZXRlKCkgLT4gdWludDY0Ogp3aXRoZHJhd19hbmRfZGVsZXRlOgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxNzYtMTc3CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICAvLyBkZWYgd2l0aGRyYXdfYW5kX2RlbGV0ZShzZWxmKSAtPiBVSW50NjQ6CiAgICBwcm90byAwIDEKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc4CiAgICAvLyBhc3NlcnQgVHhuLnNlbmRlciA9PSBHbG9iYWwuY3JlYXRvcl9hZGRyZXNzCiAgICB0eG4gU2VuZGVyCiAgICBnbG9iYWwgQ3JlYXRvckFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc5CiAgICAvLyBjb250cmFjdF9iYWxhbmNlID0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcy5iYWxhbmNlCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBhc3NlcnQgLy8gYWNjb3VudCBmdW5kZWQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgxLTE4NQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4MgogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4NAogICAgLy8gYXNzZXRfY2xvc2VfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIGR1cAogICAgaXR4bl9maWVsZCBBc3NldENsb3NlVG8KICAgIGl0eG5fZmllbGQgQXNzZXRSZWNlaXZlcgogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgxCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgxLTE4NQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODctMTkwCiAgICAvLyBpdHhuLlBheW1lbnQoCiAgICAvLyAgICAgcmVjZWl2ZXI9R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICAgICBjbG9zZV9yZW1haW5kZXJfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg4CiAgICAvLyByZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4OQogICAgLy8gY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICBkdXAKICAgIGl0eG5fZmllbGQgQ2xvc2VSZW1haW5kZXJUbwogICAgaXR4bl9maWVsZCBSZWNlaXZlcgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODcKICAgIC8vIGl0eG4uUGF5bWVudCgKICAgIGludCBwYXkKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg3LTE5MAogICAgLy8gaXR4bi5QYXltZW50KAogICAgLy8gICAgIHJlY2VpdmVyPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyAgICAgY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxOTIKICAgIC8vIHJldHVybiBjb250cmFjdF9iYWxhbmNlCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLl9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjUyCiAgICAvLyBkZWYgX19pbml0X18oc2VsZikgLT4gTm9uZToKICAgIHByb3RvIDAgMAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1MwogICAgLy8gc2VsZi5hc3NldF9pZCA9IFVJbnQ2NCgwKQogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBpbnQgMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6NTQKICAgIC8vIHNlbGYudW5pdGFyeV9wcmljZSA9IFVJbnQ2NCgwKQogICAgYnl0ZSAidW5pdGFyeV9wcmljZSIKICAgIGludCAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1NQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBGYWxzZQogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgaW50IDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBjbGFzcyBOZnRNYXJrZXRwbGFjZShhcmM0LkFSQzRDb250cmFjdCk6CiAgICBpbnQgMQogICAgcmV0dXJuCg==" }, "state": { diff --git a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/client.ts b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/client.ts index c48b6b4..b9a6970 100644 --- a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/client.ts +++ b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/artifacts/nft_marketplace/client.ts @@ -47,7 +47,7 @@ export const APP_SPEC: AppSpec = { } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MzAKICAgIC8vIGNsYXNzIE5mdE1hcmtldHBsYWNlKGFyYzQuQVJDNENvbnRyYWN0KToKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBtYWluX2JhcmVfcm91dGluZ0A5CiAgICBtZXRob2QgImJvb3RzdHJhcChhc3NldCx1aW50NjQscGF5KXZvaWQiCiAgICBtZXRob2QgImJ1eShwYXksdWludDY0KXZvaWQiCiAgICBtZXRob2QgIndpdGhkcmF3X2FuZF9kZWxldGUoKXVpbnQ2NCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIG1haW5fYm9vdHN0cmFwX3JvdXRlQDQgbWFpbl9idXlfcm91dGVANSBtYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANgogICAgZXJyIC8vIHJlamVjdCB0cmFuc2FjdGlvbgoKbWFpbl9ib290c3RyYXBfcm91dGVANDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQXNzZXRzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBidG9pCiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgY2FsbHN1YiBib290c3RyYXAKICAgIGludCAxCiAgICByZXR1cm4KCm1haW5fYnV5X3JvdXRlQDU6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjEyOQogICAgLy8gQGFyYzQuYWJpbWV0aG9kCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBjbGFzcyBOZnRNYXJrZXRwbGFjZShhcmM0LkFSQzRDb250cmFjdCk6CiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGJ0b2kKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTI5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIGNhbGxzdWIgYnV5CiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc3CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBpbnQgRGVsZXRlQXBwbGljYXRpb24KICAgID09CiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIERlbGV0ZUFwcGxpY2F0aW9uCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiB3aXRoZHJhd19hbmRfZGVsZXRlCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX2JhcmVfcm91dGluZ0A5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIHJlamVjdCB0cmFuc2FjdGlvbgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5uZnRfbWFya2V0cGxhY2UuY29udHJhY3QuTmZ0TWFya2V0cGxhY2UuYm9vdHN0cmFwKGFzc2V0OiB1aW50NjQsIHVuaXRhcnlfcHJpY2U6IHVpbnQ2NCwgbWJyX3BheTogdWludDY0KSAtPiB2b2lkOgpib290c3RyYXA6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojg2LTg5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBib290c3RyYXAoCiAgICAvLyAgICAgc2VsZiwgYXNzZXQ6IEFzc2V0LCB1bml0YXJ5X3ByaWNlOiBVSW50NjQsIG1icl9wYXk6IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAzIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTAKICAgIC8vIGFzc2VydCBUeG4uc2VuZGVyID09IEdsb2JhbC5jcmVhdG9yX2FkZHJlc3MKICAgIHR4biBTZW5kZXIKICAgIGdsb2JhbCBDcmVhdG9yQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5MQogICAgLy8gYXNzZXJ0IG5vdCBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLmlzX29wdGVkX2luKEFzc2V0KHNlbGYuYXNzZXRfaWQpKQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGludCAwCiAgICBieXRlICJhc3NldF9pZCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgYXNzZXRfaWQgZXhpc3RzCiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgIQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjkzCiAgICAvLyBhc3NlcnQgbWJyX3BheS5yZWNlaXZlciA9PSBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzCiAgICBmcmFtZV9kaWcgLTEKICAgIGd0eG5zIFJlY2VpdmVyCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5NAogICAgLy8gYXNzZXJ0IG1icl9wYXkuYW1vdW50ID09IEdsb2JhbC5taW5fYmFsYW5jZSArIEdsb2JhbC5hc3NldF9vcHRfaW5fbWluX2JhbGFuY2UKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBnbG9iYWwgTWluQmFsYW5jZQogICAgZ2xvYmFsIEFzc2V0T3B0SW5NaW5CYWxhbmNlCiAgICArCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk1CiAgICAvLyBhc3NlcnQgbm90IHNlbGYuYm9vdHN0cmFwcGVkCiAgICBpbnQgMAogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBib290c3RyYXBwZWQgZXhpc3RzCiAgICAhCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTcKICAgIC8vIHNlbGYuYXNzZXRfaWQgPSBhc3NldC5pZAogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBmcmFtZV9kaWcgLTMKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk4CiAgICAvLyBzZWxmLnVuaXRhcnlfcHJpY2UgPSB1bml0YXJ5X3ByaWNlCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgZnJhbWVfZGlnIC0yCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5OQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBUcnVlCiAgICBieXRlICJib290c3RyYXBwZWQiCiAgICBpbnQgMQogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLAogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTA0CiAgICAvLyBhc3NldF9hbW91bnQ9MCwKICAgIGludCAwCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGZyYW1lX2RpZyAtMwogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fc3VibWl0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmJ1eShidXllcl90eG46IHVpbnQ2NCwgcXVhbnRpdHk6IHVpbnQ2NCkgLT4gdm9pZDoKYnV5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMjktMTM0CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBidXkoCiAgICAvLyAgICAgc2VsZiwKICAgIC8vICAgICBidXllcl90eG46IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uLAogICAgLy8gICAgIHF1YW50aXR5OiBVSW50NjQsCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAyIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM1CiAgICAvLyBhc3NlcnQgc2VsZi51bml0YXJ5X3ByaWNlICE9IFVJbnQ2NCgwKQogICAgaW50IDAKICAgIGJ5dGUgInVuaXRhcnlfcHJpY2UiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHVuaXRhcnlfcHJpY2UgZXhpc3RzCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM2CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLnNlbmRlciA9PSBUeG4uc2VuZGVyCiAgICBmcmFtZV9kaWcgLTIKICAgIGd0eG5zIFNlbmRlcgogICAgdHhuIFNlbmRlcgogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMzcKICAgIC8vIGFzc2VydCBidXllcl90eG4ucmVjZWl2ZXIgPT0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcwogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM4CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLmFtb3VudCA9PSBzZWxmLnVuaXRhcnlfcHJpY2UgKiBxdWFudGl0eQogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBBbW91bnQKICAgIGludCAwCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayB1bml0YXJ5X3ByaWNlIGV4aXN0cwogICAgZnJhbWVfZGlnIC0xCiAgICAqCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjEzOQogICAgLy8gYXNzZXJ0IFR4bi5zZW5kZXIgIT0gR2xvYmFsLmNyZWF0b3JfYWRkcmVzcwogICAgdHhuIFNlbmRlcgogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAhPQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MS0xNDUKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MgogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTQzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1UeG4uc2VuZGVyLAogICAgdHhuIFNlbmRlcgogICAgZnJhbWVfZGlnIC0xCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGl0eG5fZmllbGQgWGZlckFzc2V0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgaW50IGF4ZmVyCiAgICBpdHhuX2ZpZWxkIFR5cGVFbnVtCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MS0xNDUKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLm5mdF9tYXJrZXRwbGFjZS5jb250cmFjdC5OZnRNYXJrZXRwbGFjZS53aXRoZHJhd19hbmRfZGVsZXRlKCkgLT4gdWludDY0Ogp3aXRoZHJhd19hbmRfZGVsZXRlOgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxNzctMTc4CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICAvLyBkZWYgd2l0aGRyYXdfYW5kX2RlbGV0ZShzZWxmKSAtPiBVSW50NjQ6CiAgICBwcm90byAwIDEKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc5CiAgICAvLyBhc3NlcnQgVHhuLnNlbmRlciA9PSBHbG9iYWwuY3JlYXRvcl9hZGRyZXNzCiAgICB0eG4gU2VuZGVyCiAgICBnbG9iYWwgQ3JlYXRvckFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgwCiAgICAvLyBjb250cmFjdF9iYWxhbmNlID0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcy5iYWxhbmNlCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBhc3NlcnQgLy8gYWNjb3VudCBmdW5kZWQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgyLTE4NgogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4MwogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg0CiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4NQogICAgLy8gYXNzZXRfY2xvc2VfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIGR1cAogICAgaXR4bl9maWVsZCBBc3NldENsb3NlVG8KICAgIGl0eG5fZmllbGQgQXNzZXRSZWNlaXZlcgogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgyCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgyLTE4NgogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODgtMTkxCiAgICAvLyBpdHhuLlBheW1lbnQoCiAgICAvLyAgICAgcmVjZWl2ZXI9R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICAgICBjbG9zZV9yZW1haW5kZXJfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg5CiAgICAvLyByZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE5MAogICAgLy8gY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICBkdXAKICAgIGl0eG5fZmllbGQgQ2xvc2VSZW1haW5kZXJUbwogICAgaXR4bl9maWVsZCBSZWNlaXZlcgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODgKICAgIC8vIGl0eG4uUGF5bWVudCgKICAgIGludCBwYXkKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg4LTE5MQogICAgLy8gaXR4bi5QYXltZW50KAogICAgLy8gICAgIHJlY2VpdmVyPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyAgICAgY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxOTMKICAgIC8vIHJldHVybiBjb250cmFjdF9iYWxhbmNlCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLl9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjUyCiAgICAvLyBkZWYgX19pbml0X18oc2VsZikgLT4gTm9uZToKICAgIHByb3RvIDAgMAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1MwogICAgLy8gc2VsZi5hc3NldF9pZCA9IFVJbnQ2NCgwKQogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBpbnQgMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6NTQKICAgIC8vIHNlbGYudW5pdGFyeV9wcmljZSA9IFVJbnQ2NCgwKQogICAgYnl0ZSAidW5pdGFyeV9wcmljZSIKICAgIGludCAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1NQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBGYWxzZQogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgaW50IDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MzAKICAgIC8vIGNsYXNzIE5mdE1hcmtldHBsYWNlKGFyYzQuQVJDNENvbnRyYWN0KToKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBtYWluX2JhcmVfcm91dGluZ0A5CiAgICBtZXRob2QgImJvb3RzdHJhcChhc3NldCx1aW50NjQscGF5KXZvaWQiCiAgICBtZXRob2QgImJ1eShwYXksdWludDY0KXZvaWQiCiAgICBtZXRob2QgIndpdGhkcmF3X2FuZF9kZWxldGUoKXVpbnQ2NCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIG1haW5fYm9vdHN0cmFwX3JvdXRlQDQgbWFpbl9idXlfcm91dGVANSBtYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANgogICAgZXJyIC8vIHJlamVjdCB0cmFuc2FjdGlvbgoKbWFpbl9ib290c3RyYXBfcm91dGVANDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQXNzZXRzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBidG9pCiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgY2FsbHN1YiBib290c3RyYXAKICAgIGludCAxCiAgICByZXR1cm4KCm1haW5fYnV5X3JvdXRlQDU6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjEyOQogICAgLy8gQGFyYzQuYWJpbWV0aG9kCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBjbGFzcyBOZnRNYXJrZXRwbGFjZShhcmM0LkFSQzRDb250cmFjdCk6CiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGJ0b2kKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTI5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIGNhbGxzdWIgYnV5CiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc2CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBpbnQgRGVsZXRlQXBwbGljYXRpb24KICAgID09CiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIERlbGV0ZUFwcGxpY2F0aW9uCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiB3aXRoZHJhd19hbmRfZGVsZXRlCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX2JhcmVfcm91dGluZ0A5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIHJlamVjdCB0cmFuc2FjdGlvbgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5uZnRfbWFya2V0cGxhY2UuY29udHJhY3QuTmZ0TWFya2V0cGxhY2UuYm9vdHN0cmFwKGFzc2V0OiB1aW50NjQsIHVuaXRhcnlfcHJpY2U6IHVpbnQ2NCwgbWJyX3BheTogdWludDY0KSAtPiB2b2lkOgpib290c3RyYXA6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojg2LTg5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBib290c3RyYXAoCiAgICAvLyAgICAgc2VsZiwgYXNzZXQ6IEFzc2V0LCB1bml0YXJ5X3ByaWNlOiBVSW50NjQsIG1icl9wYXk6IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAzIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTAKICAgIC8vIGFzc2VydCBUeG4uc2VuZGVyID09IEdsb2JhbC5jcmVhdG9yX2FkZHJlc3MKICAgIHR4biBTZW5kZXIKICAgIGdsb2JhbCBDcmVhdG9yQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5MQogICAgLy8gYXNzZXJ0IG5vdCBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLmlzX29wdGVkX2luKEFzc2V0KHNlbGYuYXNzZXRfaWQpKQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGludCAwCiAgICBieXRlICJhc3NldF9pZCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgYXNzZXRfaWQgZXhpc3RzCiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgIQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjkzCiAgICAvLyBhc3NlcnQgbWJyX3BheS5yZWNlaXZlciA9PSBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzCiAgICBmcmFtZV9kaWcgLTEKICAgIGd0eG5zIFJlY2VpdmVyCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5NAogICAgLy8gYXNzZXJ0IG1icl9wYXkuYW1vdW50ID09IEdsb2JhbC5taW5fYmFsYW5jZSArIEdsb2JhbC5hc3NldF9vcHRfaW5fbWluX2JhbGFuY2UKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBnbG9iYWwgTWluQmFsYW5jZQogICAgZ2xvYmFsIEFzc2V0T3B0SW5NaW5CYWxhbmNlCiAgICArCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk1CiAgICAvLyBhc3NlcnQgbm90IHNlbGYuYm9vdHN0cmFwcGVkCiAgICBpbnQgMAogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBib290c3RyYXBwZWQgZXhpc3RzCiAgICAhCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTcKICAgIC8vIHNlbGYuYXNzZXRfaWQgPSBhc3NldC5pZAogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBmcmFtZV9kaWcgLTMKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk4CiAgICAvLyBzZWxmLnVuaXRhcnlfcHJpY2UgPSB1bml0YXJ5X3ByaWNlCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgZnJhbWVfZGlnIC0yCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5OQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBUcnVlCiAgICBieXRlICJib290c3RyYXBwZWQiCiAgICBpbnQgMQogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLAogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTA0CiAgICAvLyBhc3NldF9hbW91bnQ9MCwKICAgIGludCAwCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGZyYW1lX2RpZyAtMwogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fc3VibWl0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmJ1eShidXllcl90eG46IHVpbnQ2NCwgcXVhbnRpdHk6IHVpbnQ2NCkgLT4gdm9pZDoKYnV5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMjktMTM0CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBidXkoCiAgICAvLyAgICAgc2VsZiwKICAgIC8vICAgICBidXllcl90eG46IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uLAogICAgLy8gICAgIHF1YW50aXR5OiBVSW50NjQsCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAyIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM1CiAgICAvLyBhc3NlcnQgc2VsZi51bml0YXJ5X3ByaWNlICE9IFVJbnQ2NCgwKQogICAgaW50IDAKICAgIGJ5dGUgInVuaXRhcnlfcHJpY2UiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHVuaXRhcnlfcHJpY2UgZXhpc3RzCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM2CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLnNlbmRlciA9PSBUeG4uc2VuZGVyCiAgICBmcmFtZV9kaWcgLTIKICAgIGd0eG5zIFNlbmRlcgogICAgdHhuIFNlbmRlcgogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMzcKICAgIC8vIGFzc2VydCBidXllcl90eG4ucmVjZWl2ZXIgPT0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcwogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM4CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLmFtb3VudCA9PSBzZWxmLnVuaXRhcnlfcHJpY2UgKiBxdWFudGl0eQogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBBbW91bnQKICAgIGludCAwCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayB1bml0YXJ5X3ByaWNlIGV4aXN0cwogICAgZnJhbWVfZGlnIC0xCiAgICAqCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MC0xNDQKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MQogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTQyCiAgICAvLyBhc3NldF9yZWNlaXZlcj1UeG4uc2VuZGVyLAogICAgdHhuIFNlbmRlcgogICAgZnJhbWVfZGlnIC0xCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGl0eG5fZmllbGQgWGZlckFzc2V0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MAogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgaW50IGF4ZmVyCiAgICBpdHhuX2ZpZWxkIFR5cGVFbnVtCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MC0xNDQKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLm5mdF9tYXJrZXRwbGFjZS5jb250cmFjdC5OZnRNYXJrZXRwbGFjZS53aXRoZHJhd19hbmRfZGVsZXRlKCkgLT4gdWludDY0Ogp3aXRoZHJhd19hbmRfZGVsZXRlOgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxNzYtMTc3CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICAvLyBkZWYgd2l0aGRyYXdfYW5kX2RlbGV0ZShzZWxmKSAtPiBVSW50NjQ6CiAgICBwcm90byAwIDEKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc4CiAgICAvLyBhc3NlcnQgVHhuLnNlbmRlciA9PSBHbG9iYWwuY3JlYXRvcl9hZGRyZXNzCiAgICB0eG4gU2VuZGVyCiAgICBnbG9iYWwgQ3JlYXRvckFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc5CiAgICAvLyBjb250cmFjdF9iYWxhbmNlID0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcy5iYWxhbmNlCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBhc3NlcnQgLy8gYWNjb3VudCBmdW5kZWQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgxLTE4NQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4MgogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4NAogICAgLy8gYXNzZXRfY2xvc2VfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIGR1cAogICAgaXR4bl9maWVsZCBBc3NldENsb3NlVG8KICAgIGl0eG5fZmllbGQgQXNzZXRSZWNlaXZlcgogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgxCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgxLTE4NQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODctMTkwCiAgICAvLyBpdHhuLlBheW1lbnQoCiAgICAvLyAgICAgcmVjZWl2ZXI9R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICAgICBjbG9zZV9yZW1haW5kZXJfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg4CiAgICAvLyByZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4OQogICAgLy8gY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICBkdXAKICAgIGl0eG5fZmllbGQgQ2xvc2VSZW1haW5kZXJUbwogICAgaXR4bl9maWVsZCBSZWNlaXZlcgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODcKICAgIC8vIGl0eG4uUGF5bWVudCgKICAgIGludCBwYXkKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg3LTE5MAogICAgLy8gaXR4bi5QYXltZW50KAogICAgLy8gICAgIHJlY2VpdmVyPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyAgICAgY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxOTIKICAgIC8vIHJldHVybiBjb250cmFjdF9iYWxhbmNlCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLl9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjUyCiAgICAvLyBkZWYgX19pbml0X18oc2VsZikgLT4gTm9uZToKICAgIHByb3RvIDAgMAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1MwogICAgLy8gc2VsZi5hc3NldF9pZCA9IFVJbnQ2NCgwKQogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBpbnQgMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6NTQKICAgIC8vIHNlbGYudW5pdGFyeV9wcmljZSA9IFVJbnQ2NCgwKQogICAgYnl0ZSAidW5pdGFyeV9wcmljZSIKICAgIGludCAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1NQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBGYWxzZQogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgaW50IDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBjbGFzcyBOZnRNYXJrZXRwbGFjZShhcmM0LkFSQzRDb250cmFjdCk6CiAgICBpbnQgMQogICAgcmV0dXJuCg==" }, "state": { diff --git a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace/contract.py b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace/contract.py index ca55480..b51d676 100644 --- a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace/contract.py +++ b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace/contract.py @@ -55,7 +55,7 @@ def __init__(self) -> None: self.bootstrapped = False """ - 문제 3 + 문제 2 bootstrap 메서드를 구현하세요. bootstrap 메서드는 앱이 판매할 에셋(ASA)을 설정하고, 단가를 설정하고 에셋이 앱 계정이 옵트인 하는 메서드입니다. @@ -105,7 +105,7 @@ def bootstrap( ).submit() """ - 문제 4 + 문제 3 buy 메서드를 구현하세요. buy 메서드는 앱에서 판매하는 에셋(ASA)을 구매할때 구매자가 호출하는 메서드입니다. @@ -136,7 +136,6 @@ def buy( assert buyer_txn.sender == Txn.sender assert buyer_txn.receiver == Global.current_application_address assert buyer_txn.amount == self.unitary_price * quantity - assert Txn.sender != Global.creator_address itxn.AssetTransfer( xfer_asset=self.asset_id, @@ -145,7 +144,7 @@ def buy( ).submit() """ - 문제 5 (쪼금 어려움 😝) + 문제 4 withdraw_and_delete 메서드를 구현하세요. withdraw_and_delete 메서드는 앱 계정에 있는 잔여 에셋(ASA)을 앱 계정으로 전송하고, diff --git a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace/deploy-config.ts b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace/deploy-config.ts index 3498a67..dba111f 100644 --- a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace/deploy-config.ts +++ b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace/deploy-config.ts @@ -6,407 +6,157 @@ import { TransactionSignerAccount } from '@algorandfoundation/algokit-utils/type export async function deploy() { console.log('=== Deploying NftMarketplaceClient ===') - // // 여러 클라이언트 생성 - // const algod = algokit.getAlgoClient() - // const indexer = algokit.getAlgoIndexerClient() - // const algorand = algokit.AlgorandClient.defaultLocalNet() - // algorand.setDefaultValidityWindow(1000) - - // // 랜덤 계정 생성 후 자금 지급 - // const deployer = await algorand.account.random() - // const buyer = await algorand.account.random() - // const lateBuyer = await algorand.account.random() - // const accounts = [deployer, buyer, lateBuyer] - - // const dispenser = await algorand.account.dispenser() - // for (let i = 0; i < accounts.length; i++) { - // await algorand.send.payment( - // { - // sender: dispenser.addr, - // receiver: accounts[i].addr, - // amount: algokit.algos(100), - // }, - // { suppressLog: true }, - // ) - // } - - // // NftMarketplace 앱 클라이언트 생성 - // const appClient = new NftMarketplaceClient( - // { - // resolveBy: 'creatorAndName', - // findExistingUsing: indexer, - // sender: deployer, - // creatorAddress: deployer.addr, - // }, - // algod, - // ) - - // // 판매할 아이유님 콘서트 티켓 에셋 생성 (아이유 짱❤️) - // const createResult = await algorand.send.assetCreate( - // { - // sender: deployer.addr, - // assetName: 'IU Concert Ticket', - // unitName: 'IU', - // total: 100n, - // }, - // { suppressLog: true }, - // ) - - // // 생성된 에셋 ID를 저장 - // const assetId = BigInt(createResult.confirmation.assetIndex!) - // console.log(`1. IU Concert Ticket 에셋 생성 완료! 에셋 아이디: ${assetId}`) - - // // NftMarketplaceClient 앱 배포 - // let unitaryPrice: number = 1 * 1_000_000 - // const app = await appClient.create.bare() - - // // NftMarketplaceClient 앱에 미니멈 밸런스 지급 - // const mbrPay = await algorand.transactions.payment({ - // sender: deployer.addr, - // receiver: app.appAddress, - // amount: algokit.algos(0.2), - // }) - - // // 앱이 판매할 준비가 되도록 Bootstrap 메서드를 호출 - // await appClient.bootstrap( - // { asset: assetId, unitaryPrice: unitaryPrice, mbrPay: mbrPay }, - // { sendParams: { fee: algokit.transactionFees(2), populateAppCallResources: true, suppressLog: true } }, - // ) - // console.log('2. 앱 부트스트래핑 완료!') - - // // NftMarketplaceClient 앱에 판매할 NFT 에셋 송금 - // await algorand.send.assetTransfer( - // { - // sender: deployer.addr, - // receiver: app.appAddress, - // assetId: assetId, - // amount: 100n, - // }, - // { suppressLog: true }, - // ) - // console.log('3. IU 티켓 에셋 앱으로 송금 완료!') - - // // 구매자 앱 클라이언트 생성. 이 앱 클라이언트는 구매자 계정과 연동됨. - // const buyerAppClient = new NftMarketplaceClient( - // { - // resolveBy: 'id', - // sender: buyer, - // id: app.appId, - // }, - // algod, - // ) - - // const lateBuyerAppClient = new NftMarketplaceClient( - // { - // resolveBy: 'id', - // sender: lateBuyer, - // id: app.appId, - // }, - // algod, - // ) - - // // 구매자가 에섯에 옵트인하고 buy 메서드를 호출하는 함수 - // async function buyAsset( - // appClient: NftMarketplaceClient, - // buyerName: string, - // buyer: TransactionSignerAccount, - // assetId: bigint, - // buyAmount: number, - // appAddr: string, - // unitaryPrice: number, - // ): Promise { - // try { - // let assetInfo = await algorand.account.getAssetInformation(buyer, assetId) - // console.log(`${buyerName}가 이미 에셋에 옵트인 되어있어요! 현재 보유한 티켓 수: ${assetInfo.balance}개`) - // } catch (e) { - // console.log(`${buyerName}가 에셋에 옵트인이 안 되어있어요. 옵트인 진행할게요~`) - // // 구매자가 NFT에 옵트인 - // await algorand.send.assetOptIn( - // { - // sender: buyer.addr, - // assetId: assetId, - // }, - // { suppressLog: true }, - // ) - // } - - // // NftMarketplaceClient buy 메서드 호출때 구매 비용 지불로 사용할 결제 트랜잭션 생성 - // const buyNftPay = await algorand.transactions.payment({ - // sender: buyer.addr, - // receiver: appAddr, - // amount: algokit.algos((unitaryPrice * buyAmount) / 1_000_000), - // }) - - // // 위 결제 트랜잭션과 NftMarketplaceClient buy 메서드를 어토믹 트랜잭션으로 동시에 호출 - // await appClient.buy( - // { - // buyerTxn: buyNftPay, - // quantity: buyAmount, - // }, - // { sendParams: { fee: algokit.transactionFees(2), populateAppCallResources: true, suppressLog: true } }, - // ) - - // const assetInfo = await algorand.account.getAssetInformation(buyer, assetId) - // console.log(`${buyerName}가 티켓 1장을 추가 구매하여 ${assetInfo.balance}개의 티켓을 보유하고 있어요!`) - // } - - // await buyAsset(buyerAppClient, 'buyer', buyer, assetId, 1, app.appAddress, unitaryPrice) - - // // // 아이유 콘서트가 인기가 너무 많아서 가격을 올림 - // // await appClient.setPrice({ - // // unitaryPrice: unitaryPrice * 2, - // // }) - // // console.log('4. IU 티켓 가격 2배로 올림!') - - // // unitaryPrice = unitaryPrice * 2 - - // // // Buyer가 친구도 데리고 가고 싶어서 1개의 티켓을 추가 구매 - // // await buyAsset(buyerAppClient, 'buyer', buyer, assetId, 1, app.appAddress, unitaryPrice) - - // // // 티켓팅에 늦은 lateBuyer가 2개의 티켓을 구매 - // // await buyAsset(lateBuyerAppClient, 'lateBuyer', lateBuyer, assetId, 2, app.appAddress, unitaryPrice) - - // // 판매자가 NftMarketplaceClient 앱을 삭제하며 수익금과 잔여 NFT 에셋을 회수 - // const returnVal = await appClient.delete.withdrawAndDelete( - // {}, - // { sendParams: { fee: algokit.transactionFees(3), populateAppCallResources: true } }, - // ) - // console.log(returnVal.return) - // console.log('5. IU 티켓 판매 종료 및 수익금 회수 완료!') - - // /* - // ========== 과제가 너무 쉬운 그대를 위하여... ========== - // 시간은 남았는데 모든 문제를 이미 다 푸셨나요? 후후후... 그럼 이것도 한번 해보세요! - - // 시나리오: 방탄소년단도 이 NftMarketplace 앱을 통해 콘서트 티켓을 팔려고 합니다. 티켓 가격은 20 Algos로 팔겠다고 합니다. - // 하이브 계정이 앱을 배포하고 티켓을 앱에 보내어 판매를 합니다. 방탄소년단의 팬이 여러분의 지갑을 개설하고 그 지갑으로 티켓 1장을 사세요. - // 그때 여러분 친구1한테 연락이 와서 콘서트 같이 가자고 연락이 옵니다. 그래서 여러분이 티켓 1장을 추가로 구매하려고 보니까 가격이 30 Algos로 - // 올라갔습니다. 그래서 어쩔 수 없이 30Algos로 티켓 1장을 추가로 삽니다. 근데 친구2도 같이 가자고 하네요. 그래서 친구2를 위해 티켓 1장을 - // 추가로 구매하려고 하는데 가격이 40Algos로 올랐습니다. 그래서 40Algos로 티켓 1장을 추가로 삽니다. 하이브는 그 뒤 충분한 티켓을 팔았다고 - // 생각하여 앱을 삭제하고 수익금을 회수합니다. - - // 지금 푸실 문제들은 아직 배우지 않은 Application Client를 사용하여 앱을 배포하고 호출하는 코드를 작성해야하는 문제들입니다. - // 이 내용은 세션 4때 다룰 내용이지만 한번 미리 도전해보세요! - // */ - // async function btsScenario(): Promise { - // console.log('=== 보너스 문제: 방탄소년단 시나리오 실행 ===') - - // // 방탄소년단과 팬 계정을 랜덤 생성 - // const bts = await algorand.account.random() - // const fan = await algorand.account.random() - // const accounts2 = [bts, fan] - - // // 계정들에 100 Algos 송금 - // for (let i = 0; i < accounts2.length; i++) { - // await algorand.send.payment( - // { - // sender: dispenser.addr, - // receiver: accounts2[i].addr, - // amount: algokit.algos(100), - // }, - // { suppressLog: true }, - // ) - // } - // /* - // 문제 1 - // 스마트계약을 만들고 티켓을 판매할 하이브 계정과 연동된 앱 클라이언트 생성하세요. - - // 앱 클라이언트는 쉽고 간편하게 스마트계약을 배포 및 호출할 수 있도록 해주는 클라이언트입니다. - - // 힌트: https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#creating-an-application-client-instance - // */ - // // - // const btsAppClient = new NftMarketplaceClient( - // { - // resolveBy: 'creatorAndName', - // findExistingUsing: indexer, - // sender: bts, - // creatorAddress: bts.addr, - // }, - // algod, - // ) - - // /* - // 문제 2 - // 위에 생성한 btsAppClient를 사용하여 앱을 배포하세요. - - // 힌트: https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#create-calls - // */ - // const btsApp = await btsAppClient.create.bare() - - // /* - // 문제 3 - // 이번에는 팬 앱 클라이언트를 생성하세요. 이 앱 클라이언트는 팬의 계정과 연동되어있습니다. - // 즉 이 클라이언트로 앱을 호출하면 팬 계정으로 호출하게 됩니다. - - // 주의사항: 이번에는 위에 판매자 앱 클라이언트랑은 다르게 이미 배포되어있는 앱의 클라이언트를 생성해야 합니다. - - // 힌트: resolveBy를 'creatorAndName'말고 다른거로 바꿔보세요. - // https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#creating-an-application-client-instance - // */ - // // - // const fanAppClient = new NftMarketplaceClient( - // { - // resolveBy: 'id', - // sender: fan, - // id: btsApp.appId, - // }, - // algod, - // ) - - // // 판매할 방탄소년단 콘서트 티켓 에셋 10장 생성 - // const createResult = await algorand.send.assetCreate( - // { - // sender: bts.addr, - // assetName: 'BTS Concert Ticket', - // unitName: 'BTS', - // total: 10n, - // }, - // { suppressLog: true }, - // ) - - // // 생성된 에셋 ID를 저장 - // const assetId = BigInt(createResult.confirmation.assetIndex!) - - // // 티켓 가격 20 Algos로 설정 이때 스마트계약은 microAlgos로 이해하기 때문에 1_000_000을 곱해줍니다. - // let unitaryPrice: number = 20 * 1_000_000 - - // /* - // 문제 4 - // 앱이 판매할 준비가 되도록 Bootstrap 메서드를 호출하세요. - - // 부트스트랩 메서드는 앱이 필요한 미니멈 밸런스를 지급하고 앱이 판매할 NFT 에셋에 옵트인하는 메서드입니다. - // 밑에 mbrPay라는 미니멈 밸런스를 지급하는 트랜잭션 객체를 만들어놓았습니다. 이 객체는 바로 Transaction Type입니다. - // 스마트계약의 bootstrap 메서드 전달값을 다시 확인해보고 이 mbrPay를 전달값으로 넣어주세요. - - // 주의사항: bootstrap 메서드는 Inner Transaction이 1개 있습니다. (앱 코드 참고) 즉 이 1개의 트랜잭션 비용을 - // bootstrap 메서드를 호출할때 같이 내줘야합니다. sendParams를 통해 fee를 0.002 Algos로 설정해주시고 - // populateAppCallResources를 true로 설정해줌으로써 필요한 reference들을 자동 기입해주도록 해주세요. - - // 힌트: 이 파일 70-74번째 줄에 있는 코드를 참고하세요. - // */ - - // // NftMarketplaceClient 앱에 미니멈 밸런스 지급 - // const mbrPay = await algorand.transactions.payment({ - // sender: bts.addr, - // receiver: btsApp.appAddress, - // amount: algokit.algos(0.2), - // }) - - // // bootstrap 메서드 호출해서 앱이 판매할 NFT 에셋에 옵트인 - // await btsAppClient.bootstrap( - // { asset: assetId, unitaryPrice: unitaryPrice, mbrPay: mbrPay }, - // { sendParams: { fee: algokit.transactionFees(2), populateAppCallResources: true, suppressLog: true } }, - // ) - // const appGlobalState = await btsAppClient.getGlobalState() - // if (appGlobalState.bootstrapped?.asNumber()) { - // console.log('방탄소년단 앱이 준비 완료되었습니다!') - // } else { - // console.log('방탄소년단 앱이 준비에 실패했습니다. 다시 확인해주세요!') - // return - // } - - // // NftMarketplaceClient 앱에 판매할 NFT 에셋 송금 - // await algorand.send.assetTransfer( - // { - // sender: bts.addr, - // receiver: btsApp.appAddress, - // assetId: assetId, - // amount: 10n, - // }, - // { suppressLog: true }, - // ) - - // // 방탄소년단 팬이 1장의 티켓을 구매. buyAsset 함수는 라인 109번째 줄에 있습니다. - // await buyAsset(fanAppClient, 'fan', fan, assetId, 1, btsApp.appAddress, unitaryPrice) - - // let assetInfo = await algorand.account.getAssetInformation(fan, assetId) - // if (assetInfo.balance === 1n) { - // console.log('팬이 성공적으로 티켓 1장을 구매했습니다!') - // } else { - // console.log('팬이 티켓 구매에 실패했습니다. 다시 확인해주세요!') - // } - // /* - // 문제 5 - // 방탄소년단 콘서트가 인기가 너무 많아서 가격을 올릴려고 합니다. - // setPrice 메서드를 호출해 티켓 가격을 10 Algos 올려서 30 Algos로 만들어주세요. - // 그러고 난 뒤 buyAsset 함수 호출뒤 다시 한번 더 티켓 가격을 10 Algos 올려 40 Algos로 만들어주세요. - - // 주의사항: 10 Algos == 10_000_000 microAlgos 현재 unitaryPrice는 microAlgos로 되어있습니다. - - // 팁: 다른 앱 메서드 호출 방법과 동일합니다~ - // */ - // // 방탄소년단 콘서트가 인기가 너무 많아서 가격을 올림 - // unitaryPrice = unitaryPrice + 10 * 1_000_000 - // await btsAppClient.setPrice({ - // unitaryPrice: unitaryPrice, - // }) - - // // 방탄소년단 팬이 친구1를 위해1장의 티켓을 추가 구매 - // await buyAsset(fanAppClient, 'fan', fan, assetId, 1, btsApp.appAddress, unitaryPrice) - - // assetInfo = await algorand.account.getAssetInformation(fan, assetId) - // if (assetInfo.balance === 2n) { - // console.log('팬이 성공적으로 티켓 1장을 추가 구매해 2장을 가지게 되었습니다!') - // } else { - // console.log('팬이 티켓 구매에 실패해 여전히 티켓 1장만 가지고있습니다 ㅠㅠ. 다시 확인해주세요!') - // return - // } - - // // 방탄소년단 콘서트가 인기가 너무 많아서 또 가격을 올림 - // unitaryPrice = unitaryPrice + 10 * 1_000_000 - // await btsAppClient.setPrice({ - // unitaryPrice: unitaryPrice, - // }) - - // // 방탄소년단 팬이 친구2를 위해1장의 티켓을 추가 구매 - // await buyAsset(fanAppClient, 'fan', fan, assetId, 1, btsApp.appAddress, unitaryPrice) - - // assetInfo = await algorand.account.getAssetInformation(fan, assetId) - // if (assetInfo.balance === 3n) { - // console.log('팬이 성공적으로 티켓 1장을 추가 구매해 3장을 가지게 되었습니다!') - // } else { - // console.log('팬이 티켓 구매에 실패해 여전히 티켓 2장만 가지고있습니다 ㅠㅠ. 다시 확인해주세요!') - // return - // } - // /* - // 문제 6 - // 방탄소년단이 충분한 티켓을 팔았다고 생각합니다. 앱을 삭제하고 수익금을 회수할 수 있도록 withdrawAndDelete 메서드를 호출하세요. - - // withdrawAndDelete 메서드는 OnComplete Actions가 DeleteApplication으로 설정된 특별한 메서드입니다. - // 앱 클라이언트에는 delete라는 property가 있습니다. 이 delete property에 withdrawAndDelete 메서드가 있으니 이 메서드를 호출하시면 됩니다. - - // 주의사항: withdrawAndDelete 메서드는 Inner Transaction이 두개나 있습니다. (앱 코드 참고) 즉 이 두개의 트랜잭션 비용을 - // withdrawAndDelete를 호출할때 같이 내줘야합니다. sendParams를 통해 fee를 0.003 Algos로 설정해주시고 - // populateAppCallResources를 true로 설정해줌으로써 필요한 reference들을 자동 기입해주도록 해주세요. - - // 힌트: https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#update-and-delete-calls - // */ - - // // 판매자가 NftMarketplaceClient 앱을 삭제하며 수익금과 잔여 NFT 에셋을 회수 - - // let btsAccountInfo = await algorand.account.getInformation(bts) - // console.log( - // `방탄소년단 계정이 앱을 삭제하기 전에는 ${btsAccountInfo.amount / 1_000_000} Algos를 보유하고 있습니다.`, - // ) - - // await btsAppClient.delete.withdrawAndDelete( - // {}, - // { sendParams: { fee: algokit.transactionFees(3), populateAppCallResources: true } }, - // ) - - // btsAccountInfo = await algorand.account.getInformation(bts) - // const btsAccountBalance = btsAccountInfo.amount / 1_000_000 - // if (btsAccountBalance == 189.989) { - // console.log(`방탄소년단이 성공적으로 앱을 삭제하고 수익금 90 Algos를 회수했습니다!`) - // } else { - // console.log(`방탄소년단이 앱 삭제에 실패했습니다. 현재 계정 잔액: ${btsAccountBalance} Algos`) - // } - // } - - // /* - // 문제 7 - // 보너스 문제를 푸셨다면 아래 주석을 해제하고 await btsScenario를 실행하세요! - // */ - // // await btsScenario() + // 여러 클라이언트 생성 + const algod = algokit.getAlgoClient() + const indexer = algokit.getAlgoIndexerClient() + const algorand = algokit.AlgorandClient.defaultLocalNet() + algorand.setDefaultValidityWindow(1000) + + // 랜덤 계정 생성 후 자금 지급 + const deployer = await algorand.account.random() + const buyer = await algorand.account.random() + const lateBuyer = await algorand.account.random() + const accounts = [deployer, buyer, lateBuyer] + + const dispenser = await algorand.account.dispenser() + for (let i = 0; i < accounts.length; i++) { + await algorand.send.payment( + { + sender: dispenser.addr, + receiver: accounts[i].addr, + amount: algokit.algos(100), + }, + { suppressLog: true }, + ) + } + + // NftMarketplace 앱 클라이언트 생성 + const appClient = new NftMarketplaceClient( + { + resolveBy: 'creatorAndName', + findExistingUsing: indexer, + sender: deployer, + creatorAddress: deployer.addr, + }, + algod, + ) + + // 판매할 아이유님 콘서트 티켓 에셋 생성 (아이유 짱❤️) + const createResult = await algorand.send.assetCreate( + { + sender: deployer.addr, + assetName: 'IU Concert Ticket', + unitName: 'IU', + total: 100n, + }, + { suppressLog: true }, + ) + + // 생성된 에셋 ID를 저장 + const assetId = BigInt(createResult.confirmation.assetIndex!) + console.log(`1. IU Concert Ticket 에셋 생성 완료! 에셋 아이디: ${assetId}`) + + // NftMarketplaceClient 앱 배포 + let unitaryPrice: number = 1 * 1_000_000 + const app = await appClient.create.bare() + + // NftMarketplaceClient 앱에 미니멈 밸런스 지급 + const mbrPay = await algorand.transactions.payment({ + sender: deployer.addr, + receiver: app.appAddress, + amount: algokit.algos(0.2), + }) + + // 앱이 판매할 준비가 되도록 Bootstrap 메서드를 호출 + await appClient.bootstrap( + { asset: assetId, unitaryPrice: unitaryPrice, mbrPay: mbrPay }, + { sendParams: { fee: algokit.transactionFees(2), populateAppCallResources: true, suppressLog: true } }, + ) + console.log('2. 앱 부트스트래핑 완료!') + + // NftMarketplaceClient 앱에 판매할 NFT 에셋 송금 + await algorand.send.assetTransfer( + { + sender: deployer.addr, + receiver: app.appAddress, + assetId: assetId, + amount: 100n, + }, + { suppressLog: true }, + ) + console.log('3. IU 티켓 에셋 앱으로 송금 완료!') + + // 구매자 앱 클라이언트 생성. 이 앱 클라이언트는 구매자 계정과 연동됨. + const buyerAppClient = new NftMarketplaceClient( + { + resolveBy: 'id', + sender: buyer, + id: app.appId, + }, + algod, + ) + + const lateBuyerAppClient = new NftMarketplaceClient( + { + resolveBy: 'id', + sender: lateBuyer, + id: app.appId, + }, + algod, + ) + + // 구매자가 에섯에 옵트인하고 buy 메서드를 호출하는 함수 + async function buyAsset( + appClient: NftMarketplaceClient, + buyerName: string, + buyer: TransactionSignerAccount, + assetId: bigint, + buyAmount: number, + appAddr: string, + unitaryPrice: number, + ): Promise { + try { + let assetInfo = await algorand.account.getAssetInformation(buyer, assetId) + console.log(`${buyerName}가 이미 에셋에 옵트인 되어있어요! 현재 보유한 티켓 수: ${assetInfo.balance}개`) + } catch (e) { + console.log(`${buyerName}가 에셋에 옵트인이 안 되어있어요. 옵트인 진행할게요~`) + // 구매자가 NFT에 옵트인 + await algorand.send.assetOptIn( + { + sender: buyer.addr, + assetId: assetId, + }, + { suppressLog: true }, + ) + } + + // NftMarketplaceClient buy 메서드 호출때 구매 비용 지불로 사용할 결제 트랜잭션 생성 + const buyNftPay = await algorand.transactions.payment({ + sender: buyer.addr, + receiver: appAddr, + amount: algokit.algos((unitaryPrice * buyAmount) / 1_000_000), + }) + + // 위 결제 트랜잭션과 NftMarketplaceClient buy 메서드를 어토믹 트랜잭션으로 동시에 호출 + await appClient.buy( + { + buyerTxn: buyNftPay, + quantity: buyAmount, + }, + { sendParams: { fee: algokit.transactionFees(2), populateAppCallResources: true, suppressLog: true } }, + ) + + const assetInfo = await algorand.account.getAssetInformation(buyer, assetId) + console.log(`${buyerName}가 티켓 1장을 추가 구매하여 ${assetInfo.balance}개의 티켓을 보유하고 있어요!`) + } + + await buyAsset(buyerAppClient, 'buyer', buyer, assetId, 1, app.appAddress, unitaryPrice) + + // 판매자가 NftMarketplaceClient 앱을 삭제하며 수익금과 잔여 NFT 에셋을 회수 + const returnVal = await appClient.delete.withdrawAndDelete( + {}, + { sendParams: { fee: algokit.transactionFees(3), populateAppCallResources: true } }, + ) + console.log('총 수익금: ', returnVal.return) + console.log('4. IU 티켓 판매 종료 및 수익금 회수 완료!') } diff --git a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace_list/deploy-config.ts b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace_list/deploy-config.ts index 03b9e94..72783cf 100644 --- a/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace_list/deploy-config.ts +++ b/projects/orakle-nft-marketplace-app-contracts/smart_contracts/nft_marketplace_list/deploy-config.ts @@ -8,22 +8,21 @@ export async function deploy() { // 여러 클라이언트 생성 const algod = algokit.getAlgoClient() const indexer = algokit.getAlgoIndexerClient() - const algorand = algokit.AlgorandClient.testNet() + const algorand = algokit.AlgorandClient.defaultLocalNet() algorand.setDefaultValidityWindow(1000) // 랜덤 계정 생성 후 자금 지급 - // const deployer = await algorand.account.random() - const deployer = await algorand.account.fromMnemonic(process.env.MY_ACCOUNT_MNEMONIC!, process.env.MY_ACCOUNT_SENDER!) - - // const dispenser = await algorand.account.dispenser() - // await algorand.send.payment( - // { - // sender: dispenser.addr, - // receiver: deployer.addr, - // amount: algokit.algos(100), - // }, - // { suppressLog: true }, - // ) + const deployer = await algorand.account.random() + + const dispenser = await algorand.account.dispenser() + await algorand.send.payment( + { + sender: dispenser.addr, + receiver: deployer.addr, + amount: algokit.algos(100), + }, + { suppressLog: true }, + ) const appClient = new NftMarketplaceListClient( { diff --git a/projects/orakle-nft-marketplace-app-frontend/src/components/Buy.tsx b/projects/orakle-nft-marketplace-app-frontend/src/components/Buy.tsx index ebc61e9..d2c22ab 100644 --- a/projects/orakle-nft-marketplace-app-frontend/src/components/Buy.tsx +++ b/projects/orakle-nft-marketplace-app-frontend/src/components/Buy.tsx @@ -4,8 +4,8 @@ import { useAtomValue } from 'jotai' import { useSnackbar } from 'notistack' import { useState } from 'react' import { algorandClientAtom, appDetailsListAtom } from '../atoms' -import { NftMarketplaceClient } from '../contracts/NftMarketplace' import * as methods from '../methods' +import { getCurrentNftmClient } from '../utils/getCurrentNftmClient' interface BuyInterface { openModal: boolean @@ -36,14 +36,7 @@ const Buy = ({ openModal, setModalState, currentAppId, unitaryPrice }: BuyInterf return } - const nftmClient = new NftMarketplaceClient( - { - resolveBy: 'id', - id: currentAppId, - sender: { addr: activeAddress!, signer }, - }, - algorandClient.client.algod, - ) + const nftmClient = getCurrentNftmClient(algorandClient, currentAppId, activeAddress, signer) let currentAppDetails diff --git a/projects/orakle-nft-marketplace-app-frontend/src/components/Header.tsx b/projects/orakle-nft-marketplace-app-frontend/src/components/Header.tsx index ae68bfc..1b8b8c3 100644 --- a/projects/orakle-nft-marketplace-app-frontend/src/components/Header.tsx +++ b/projects/orakle-nft-marketplace-app-frontend/src/components/Header.tsx @@ -4,6 +4,7 @@ import { useState } from 'react' import { isSellingAtom } from '../atoms' import { ellipseAddress } from '../utils/ellipseAddress' import ConnectWallet from './ConnectWallet' +import MintNft from './MintNft' import Sell from './Sell' import Withdraw from './Withdraw' @@ -14,7 +15,7 @@ export function Header() { const [openWalletModal, setOpenWalletModal] = useState(false) const [openSellModal, setOpenSellModal] = useState(false) const [openWithdrawModal, setOpenWithdrawModal] = useState(false) - // const [openMintModal, setOpenMintModal] = useState(false) + const [openMintModal, setOpenMintModal] = useState(false) const toggleWalletModal = () => { setOpenWalletModal((prev) => !prev) @@ -25,20 +26,19 @@ export function Header() { const toggleWithdrawModal = () => { setOpenWithdrawModal((prev) => !prev) } - // const toggleMintModal = () => { - // setOpenMintModal((prev) => !prev) - // } + const toggleMintModal = () => { + setOpenMintModal((prev) => !prev) + } return (

Algorand X Orakle NFT Marketplace

- - {/* */}
+
) } diff --git a/projects/orakle-nft-marketplace-app-frontend/src/components/MintNft.tsx b/projects/orakle-nft-marketplace-app-frontend/src/components/MintNft.tsx index da771d3..f11dfd9 100644 --- a/projects/orakle-nft-marketplace-app-frontend/src/components/MintNft.tsx +++ b/projects/orakle-nft-marketplace-app-frontend/src/components/MintNft.tsx @@ -34,11 +34,12 @@ const MintNft = ({ openModal, setModalState }: BuyInterface) => { unitName: 'NFT', total: 10n, decimals: 1, - url: `ipfs://QmV1dyum28Y4Nhz6wVRTgb1nc6CwqHUwSvkyji1sPGzt6X/#arc3`, + url: `ipfs://QmUGFmpbvqsSoNP8yhLuVwQ7vYJ5MQ7VuEjrXNUUfifewx/#arc3`, }) console.log(result?.confirmation.assetIndex) setLoading(false) + window.location.reload() } return ( diff --git a/projects/orakle-nft-marketplace-app-frontend/src/components/NftCardSection.tsx b/projects/orakle-nft-marketplace-app-frontend/src/components/NftCardSection.tsx index 28d34f5..d4f9d3f 100644 --- a/projects/orakle-nft-marketplace-app-frontend/src/components/NftCardSection.tsx +++ b/projects/orakle-nft-marketplace-app-frontend/src/components/NftCardSection.tsx @@ -14,11 +14,15 @@ export function NftCardSection() {
{activeAddress ? ( healthExternal ? ( -
- {appDetailsList.map((data) => ( - - ))} -
+ appDetailsList.length > 0 ? ( +
+ {appDetailsList.map((data) => ( + + ))} +
+ ) : ( +

No NFTs available

+ ) ) : (
{loadingList.map((data) => ( diff --git a/projects/orakle-nft-marketplace-app-frontend/src/components/Sell.tsx b/projects/orakle-nft-marketplace-app-frontend/src/components/Sell.tsx index 26dc96c..fbab255 100644 --- a/projects/orakle-nft-marketplace-app-frontend/src/components/Sell.tsx +++ b/projects/orakle-nft-marketplace-app-frontend/src/components/Sell.tsx @@ -3,8 +3,8 @@ import { useAtomValue } from 'jotai' import { useSnackbar } from 'notistack' import { useState } from 'react' import { algorandClientAtom, assetHoldingAtom, listClientAtom } from '../atoms' -import { NftMarketplaceClient } from '../contracts/NftMarketplace' import * as methods from '../methods' +import { getCurrentNftmClient } from '../utils/getCurrentNftmClient' interface SellInterface { openModal: boolean @@ -39,14 +39,7 @@ const Sell = ({ openModal, setModalState }: SellInterface) => { return } - const nftmClient = new NftMarketplaceClient( - { - resolveBy: 'id', - id: 0, - sender: { addr: activeAddress!, signer }, - }, - algorandClient?.client.algod, - ) + const nftmClient = await getCurrentNftmClient(algorandClient, 0, activeAddress, signer) try { await methods.create( diff --git a/projects/orakle-nft-marketplace-app-frontend/src/components/Withdraw.tsx b/projects/orakle-nft-marketplace-app-frontend/src/components/Withdraw.tsx index 97d6970..b8c19a0 100644 --- a/projects/orakle-nft-marketplace-app-frontend/src/components/Withdraw.tsx +++ b/projects/orakle-nft-marketplace-app-frontend/src/components/Withdraw.tsx @@ -5,6 +5,7 @@ import { useState } from 'react' import { algorandClientAtom, appDetailsListAtom, listClientAtom } from '../atoms' import { NftMarketplaceClient } from '../contracts/NftMarketplace' import * as methods from '../methods' +import { getCurrentNftmClient } from '../utils/getCurrentNftmClient' interface WithdrawInterface { openModal: boolean @@ -45,14 +46,8 @@ const Withdraw = ({ openModal, setModalState }: WithdrawInterface) => { for (const appDetails of appDetailsList) { if (appDetails.creator == activeAddress) { - nftmClient = new NftMarketplaceClient( - { - resolveBy: 'id', - id: appDetails.appId, - sender: { addr: activeAddress!, signer }, - }, - algorandClient.client.algod, - ) + nftmClient = await getCurrentNftmClient(algorandClient, appDetails.appId, activeAddress, signer) + myAppId = appDetails.appId break } @@ -65,7 +60,7 @@ const Withdraw = ({ openModal, setModalState }: WithdrawInterface) => { } try { - await methods.deleteApp(algorandClient, nftmClient, listClient, activeAddress, Number(myAppId))() + await methods.deleteApp(nftmClient, listClient, Number(myAppId))() } catch (error) { enqueueSnackbar('Error deleting the app', { variant: 'error' }) setLoading(false) diff --git a/projects/orakle-nft-marketplace-app-frontend/src/contracts/NftMarketplace.ts b/projects/orakle-nft-marketplace-app-frontend/src/contracts/NftMarketplace.ts index c48b6b4..b9a6970 100644 --- a/projects/orakle-nft-marketplace-app-frontend/src/contracts/NftMarketplace.ts +++ b/projects/orakle-nft-marketplace-app-frontend/src/contracts/NftMarketplace.ts @@ -47,7 +47,7 @@ export const APP_SPEC: AppSpec = { } }, "source": { - "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MzAKICAgIC8vIGNsYXNzIE5mdE1hcmtldHBsYWNlKGFyYzQuQVJDNENvbnRyYWN0KToKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBtYWluX2JhcmVfcm91dGluZ0A5CiAgICBtZXRob2QgImJvb3RzdHJhcChhc3NldCx1aW50NjQscGF5KXZvaWQiCiAgICBtZXRob2QgImJ1eShwYXksdWludDY0KXZvaWQiCiAgICBtZXRob2QgIndpdGhkcmF3X2FuZF9kZWxldGUoKXVpbnQ2NCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIG1haW5fYm9vdHN0cmFwX3JvdXRlQDQgbWFpbl9idXlfcm91dGVANSBtYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANgogICAgZXJyIC8vIHJlamVjdCB0cmFuc2FjdGlvbgoKbWFpbl9ib290c3RyYXBfcm91dGVANDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQXNzZXRzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBidG9pCiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgY2FsbHN1YiBib290c3RyYXAKICAgIGludCAxCiAgICByZXR1cm4KCm1haW5fYnV5X3JvdXRlQDU6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjEyOQogICAgLy8gQGFyYzQuYWJpbWV0aG9kCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBjbGFzcyBOZnRNYXJrZXRwbGFjZShhcmM0LkFSQzRDb250cmFjdCk6CiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGJ0b2kKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTI5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIGNhbGxzdWIgYnV5CiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc3CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBpbnQgRGVsZXRlQXBwbGljYXRpb24KICAgID09CiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIERlbGV0ZUFwcGxpY2F0aW9uCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiB3aXRoZHJhd19hbmRfZGVsZXRlCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX2JhcmVfcm91dGluZ0A5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIHJlamVjdCB0cmFuc2FjdGlvbgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5uZnRfbWFya2V0cGxhY2UuY29udHJhY3QuTmZ0TWFya2V0cGxhY2UuYm9vdHN0cmFwKGFzc2V0OiB1aW50NjQsIHVuaXRhcnlfcHJpY2U6IHVpbnQ2NCwgbWJyX3BheTogdWludDY0KSAtPiB2b2lkOgpib290c3RyYXA6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojg2LTg5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBib290c3RyYXAoCiAgICAvLyAgICAgc2VsZiwgYXNzZXQ6IEFzc2V0LCB1bml0YXJ5X3ByaWNlOiBVSW50NjQsIG1icl9wYXk6IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAzIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTAKICAgIC8vIGFzc2VydCBUeG4uc2VuZGVyID09IEdsb2JhbC5jcmVhdG9yX2FkZHJlc3MKICAgIHR4biBTZW5kZXIKICAgIGdsb2JhbCBDcmVhdG9yQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5MQogICAgLy8gYXNzZXJ0IG5vdCBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLmlzX29wdGVkX2luKEFzc2V0KHNlbGYuYXNzZXRfaWQpKQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGludCAwCiAgICBieXRlICJhc3NldF9pZCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgYXNzZXRfaWQgZXhpc3RzCiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgIQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjkzCiAgICAvLyBhc3NlcnQgbWJyX3BheS5yZWNlaXZlciA9PSBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzCiAgICBmcmFtZV9kaWcgLTEKICAgIGd0eG5zIFJlY2VpdmVyCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5NAogICAgLy8gYXNzZXJ0IG1icl9wYXkuYW1vdW50ID09IEdsb2JhbC5taW5fYmFsYW5jZSArIEdsb2JhbC5hc3NldF9vcHRfaW5fbWluX2JhbGFuY2UKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBnbG9iYWwgTWluQmFsYW5jZQogICAgZ2xvYmFsIEFzc2V0T3B0SW5NaW5CYWxhbmNlCiAgICArCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk1CiAgICAvLyBhc3NlcnQgbm90IHNlbGYuYm9vdHN0cmFwcGVkCiAgICBpbnQgMAogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBib290c3RyYXBwZWQgZXhpc3RzCiAgICAhCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTcKICAgIC8vIHNlbGYuYXNzZXRfaWQgPSBhc3NldC5pZAogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBmcmFtZV9kaWcgLTMKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk4CiAgICAvLyBzZWxmLnVuaXRhcnlfcHJpY2UgPSB1bml0YXJ5X3ByaWNlCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgZnJhbWVfZGlnIC0yCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5OQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBUcnVlCiAgICBieXRlICJib290c3RyYXBwZWQiCiAgICBpbnQgMQogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLAogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTA0CiAgICAvLyBhc3NldF9hbW91bnQ9MCwKICAgIGludCAwCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGZyYW1lX2RpZyAtMwogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fc3VibWl0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmJ1eShidXllcl90eG46IHVpbnQ2NCwgcXVhbnRpdHk6IHVpbnQ2NCkgLT4gdm9pZDoKYnV5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMjktMTM0CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBidXkoCiAgICAvLyAgICAgc2VsZiwKICAgIC8vICAgICBidXllcl90eG46IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uLAogICAgLy8gICAgIHF1YW50aXR5OiBVSW50NjQsCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAyIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM1CiAgICAvLyBhc3NlcnQgc2VsZi51bml0YXJ5X3ByaWNlICE9IFVJbnQ2NCgwKQogICAgaW50IDAKICAgIGJ5dGUgInVuaXRhcnlfcHJpY2UiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHVuaXRhcnlfcHJpY2UgZXhpc3RzCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM2CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLnNlbmRlciA9PSBUeG4uc2VuZGVyCiAgICBmcmFtZV9kaWcgLTIKICAgIGd0eG5zIFNlbmRlcgogICAgdHhuIFNlbmRlcgogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMzcKICAgIC8vIGFzc2VydCBidXllcl90eG4ucmVjZWl2ZXIgPT0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcwogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM4CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLmFtb3VudCA9PSBzZWxmLnVuaXRhcnlfcHJpY2UgKiBxdWFudGl0eQogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBBbW91bnQKICAgIGludCAwCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayB1bml0YXJ5X3ByaWNlIGV4aXN0cwogICAgZnJhbWVfZGlnIC0xCiAgICAqCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjEzOQogICAgLy8gYXNzZXJ0IFR4bi5zZW5kZXIgIT0gR2xvYmFsLmNyZWF0b3JfYWRkcmVzcwogICAgdHhuIFNlbmRlcgogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAhPQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MS0xNDUKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MgogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTQzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1UeG4uc2VuZGVyLAogICAgdHhuIFNlbmRlcgogICAgZnJhbWVfZGlnIC0xCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGl0eG5fZmllbGQgWGZlckFzc2V0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgaW50IGF4ZmVyCiAgICBpdHhuX2ZpZWxkIFR5cGVFbnVtCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MS0xNDUKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLm5mdF9tYXJrZXRwbGFjZS5jb250cmFjdC5OZnRNYXJrZXRwbGFjZS53aXRoZHJhd19hbmRfZGVsZXRlKCkgLT4gdWludDY0Ogp3aXRoZHJhd19hbmRfZGVsZXRlOgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxNzctMTc4CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICAvLyBkZWYgd2l0aGRyYXdfYW5kX2RlbGV0ZShzZWxmKSAtPiBVSW50NjQ6CiAgICBwcm90byAwIDEKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc5CiAgICAvLyBhc3NlcnQgVHhuLnNlbmRlciA9PSBHbG9iYWwuY3JlYXRvcl9hZGRyZXNzCiAgICB0eG4gU2VuZGVyCiAgICBnbG9iYWwgQ3JlYXRvckFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgwCiAgICAvLyBjb250cmFjdF9iYWxhbmNlID0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcy5iYWxhbmNlCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBhc3NlcnQgLy8gYWNjb3VudCBmdW5kZWQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgyLTE4NgogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4MwogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg0CiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4NQogICAgLy8gYXNzZXRfY2xvc2VfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIGR1cAogICAgaXR4bl9maWVsZCBBc3NldENsb3NlVG8KICAgIGl0eG5fZmllbGQgQXNzZXRSZWNlaXZlcgogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgyCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgyLTE4NgogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODgtMTkxCiAgICAvLyBpdHhuLlBheW1lbnQoCiAgICAvLyAgICAgcmVjZWl2ZXI9R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICAgICBjbG9zZV9yZW1haW5kZXJfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg5CiAgICAvLyByZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE5MAogICAgLy8gY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICBkdXAKICAgIGl0eG5fZmllbGQgQ2xvc2VSZW1haW5kZXJUbwogICAgaXR4bl9maWVsZCBSZWNlaXZlcgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODgKICAgIC8vIGl0eG4uUGF5bWVudCgKICAgIGludCBwYXkKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg4LTE5MQogICAgLy8gaXR4bi5QYXltZW50KAogICAgLy8gICAgIHJlY2VpdmVyPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyAgICAgY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxOTMKICAgIC8vIHJldHVybiBjb250cmFjdF9iYWxhbmNlCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLl9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjUyCiAgICAvLyBkZWYgX19pbml0X18oc2VsZikgLT4gTm9uZToKICAgIHByb3RvIDAgMAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1MwogICAgLy8gc2VsZi5hc3NldF9pZCA9IFVJbnQ2NCgwKQogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBpbnQgMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6NTQKICAgIC8vIHNlbGYudW5pdGFyeV9wcmljZSA9IFVJbnQ2NCgwKQogICAgYnl0ZSAidW5pdGFyeV9wcmljZSIKICAgIGludCAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1NQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBGYWxzZQogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgaW50IDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", + "approval": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmFwcHJvdmFsX3Byb2dyYW06CiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYm56IG1haW5fZW50cnlwb2ludEAyCiAgICBjYWxsc3ViIF9faW5pdF9fCgptYWluX2VudHJ5cG9pbnRAMjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MzAKICAgIC8vIGNsYXNzIE5mdE1hcmtldHBsYWNlKGFyYzQuQVJDNENvbnRyYWN0KToKICAgIHR4biBOdW1BcHBBcmdzCiAgICBieiBtYWluX2JhcmVfcm91dGluZ0A5CiAgICBtZXRob2QgImJvb3RzdHJhcChhc3NldCx1aW50NjQscGF5KXZvaWQiCiAgICBtZXRob2QgImJ1eShwYXksdWludDY0KXZvaWQiCiAgICBtZXRob2QgIndpdGhkcmF3X2FuZF9kZWxldGUoKXVpbnQ2NCIKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDAKICAgIG1hdGNoIG1haW5fYm9vdHN0cmFwX3JvdXRlQDQgbWFpbl9idXlfcm91dGVANSBtYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANgogICAgZXJyIC8vIHJlamVjdCB0cmFuc2FjdGlvbgoKbWFpbl9ib290c3RyYXBfcm91dGVANDoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIE9uQ29tcGxldGlvbiBpcyBOb09wCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMQogICAgYnRvaQogICAgdHhuYXMgQXNzZXRzCiAgICB0eG5hIEFwcGxpY2F0aW9uQXJncyAyCiAgICBidG9pCiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6ODYKICAgIC8vIEBhcmM0LmFiaW1ldGhvZAogICAgY2FsbHN1YiBib290c3RyYXAKICAgIGludCAxCiAgICByZXR1cm4KCm1haW5fYnV5X3JvdXRlQDU6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjEyOQogICAgLy8gQGFyYzQuYWJpbWV0aG9kCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICAhCiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIE5vT3AKICAgIHR4biBBcHBsaWNhdGlvbklECiAgICBhc3NlcnQgLy8gaXMgbm90IGNyZWF0aW5nCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBjbGFzcyBOZnRNYXJrZXRwbGFjZShhcmM0LkFSQzRDb250cmFjdCk6CiAgICB0eG4gR3JvdXBJbmRleAogICAgaW50IDEKICAgIC0KICAgIGR1cAogICAgZ3R4bnMgVHlwZUVudW0KICAgIGludCBwYXkKICAgID09CiAgICBhc3NlcnQgLy8gdHJhbnNhY3Rpb24gdHlwZSBpcyBwYXkKICAgIHR4bmEgQXBwbGljYXRpb25BcmdzIDEKICAgIGJ0b2kKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTI5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIGNhbGxzdWIgYnV5CiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX3dpdGhkcmF3X2FuZF9kZWxldGVfcm91dGVANjoKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc2CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICB0eG4gT25Db21wbGV0aW9uCiAgICBpbnQgRGVsZXRlQXBwbGljYXRpb24KICAgID09CiAgICBhc3NlcnQgLy8gT25Db21wbGV0aW9uIGlzIERlbGV0ZUFwcGxpY2F0aW9uCiAgICB0eG4gQXBwbGljYXRpb25JRAogICAgYXNzZXJ0IC8vIGlzIG5vdCBjcmVhdGluZwogICAgY2FsbHN1YiB3aXRoZHJhd19hbmRfZGVsZXRlCiAgICBpdG9iCiAgICBieXRlIDB4MTUxZjdjNzUKICAgIHN3YXAKICAgIGNvbmNhdAogICAgbG9nCiAgICBpbnQgMQogICAgcmV0dXJuCgptYWluX2JhcmVfcm91dGluZ0A5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTozMAogICAgLy8gY2xhc3MgTmZ0TWFya2V0cGxhY2UoYXJjNC5BUkM0Q29udHJhY3QpOgogICAgdHhuIE9uQ29tcGxldGlvbgogICAgIQogICAgYXNzZXJ0IC8vIHJlamVjdCB0cmFuc2FjdGlvbgogICAgdHhuIEFwcGxpY2F0aW9uSUQKICAgICEKICAgIGFzc2VydCAvLyBpcyBjcmVhdGluZwogICAgaW50IDEKICAgIHJldHVybgoKCi8vIHNtYXJ0X2NvbnRyYWN0cy5uZnRfbWFya2V0cGxhY2UuY29udHJhY3QuTmZ0TWFya2V0cGxhY2UuYm9vdHN0cmFwKGFzc2V0OiB1aW50NjQsIHVuaXRhcnlfcHJpY2U6IHVpbnQ2NCwgbWJyX3BheTogdWludDY0KSAtPiB2b2lkOgpib290c3RyYXA6CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojg2LTg5CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBib290c3RyYXAoCiAgICAvLyAgICAgc2VsZiwgYXNzZXQ6IEFzc2V0LCB1bml0YXJ5X3ByaWNlOiBVSW50NjQsIG1icl9wYXk6IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAzIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTAKICAgIC8vIGFzc2VydCBUeG4uc2VuZGVyID09IEdsb2JhbC5jcmVhdG9yX2FkZHJlc3MKICAgIHR4biBTZW5kZXIKICAgIGdsb2JhbCBDcmVhdG9yQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5MQogICAgLy8gYXNzZXJ0IG5vdCBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLmlzX29wdGVkX2luKEFzc2V0KHNlbGYuYXNzZXRfaWQpKQogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIGludCAwCiAgICBieXRlICJhc3NldF9pZCIKICAgIGFwcF9nbG9iYWxfZ2V0X2V4CiAgICBhc3NlcnQgLy8gY2hlY2sgYXNzZXRfaWQgZXhpc3RzCiAgICBhc3NldF9ob2xkaW5nX2dldCBBc3NldEJhbGFuY2UKICAgIGJ1cnkgMQogICAgIQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjkzCiAgICAvLyBhc3NlcnQgbWJyX3BheS5yZWNlaXZlciA9PSBHbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzCiAgICBmcmFtZV9kaWcgLTEKICAgIGd0eG5zIFJlY2VpdmVyCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5NAogICAgLy8gYXNzZXJ0IG1icl9wYXkuYW1vdW50ID09IEdsb2JhbC5taW5fYmFsYW5jZSArIEdsb2JhbC5hc3NldF9vcHRfaW5fbWluX2JhbGFuY2UKICAgIGZyYW1lX2RpZyAtMQogICAgZ3R4bnMgQW1vdW50CiAgICBnbG9iYWwgTWluQmFsYW5jZQogICAgZ2xvYmFsIEFzc2V0T3B0SW5NaW5CYWxhbmNlCiAgICArCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk1CiAgICAvLyBhc3NlcnQgbm90IHNlbGYuYm9vdHN0cmFwcGVkCiAgICBpbnQgMAogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBib290c3RyYXBwZWQgZXhpc3RzCiAgICAhCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6OTcKICAgIC8vIHNlbGYuYXNzZXRfaWQgPSBhc3NldC5pZAogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBmcmFtZV9kaWcgLTMKICAgIGFwcF9nbG9iYWxfcHV0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5Ojk4CiAgICAvLyBzZWxmLnVuaXRhcnlfcHJpY2UgPSB1bml0YXJ5X3ByaWNlCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgZnJhbWVfZGlnIC0yCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo5OQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBUcnVlCiAgICBieXRlICJib290c3RyYXBwZWQiCiAgICBpbnQgMQogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3VycmVudF9hcHBsaWNhdGlvbl9hZGRyZXNzLAogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTA0CiAgICAvLyBhc3NldF9hbW91bnQ9MCwKICAgIGludCAwCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGZyYW1lX2RpZyAtMwogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTAxLTEwNQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9YXNzZXQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9R2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcywKICAgIC8vICAgICBhc3NldF9hbW91bnQ9MCwKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fc3VibWl0CiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmJ1eShidXllcl90eG46IHVpbnQ2NCwgcXVhbnRpdHk6IHVpbnQ2NCkgLT4gdm9pZDoKYnV5OgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMjktMTM0CiAgICAvLyBAYXJjNC5hYmltZXRob2QKICAgIC8vIGRlZiBidXkoCiAgICAvLyAgICAgc2VsZiwKICAgIC8vICAgICBidXllcl90eG46IGd0eG4uUGF5bWVudFRyYW5zYWN0aW9uLAogICAgLy8gICAgIHF1YW50aXR5OiBVSW50NjQsCiAgICAvLyApIC0+IE5vbmU6CiAgICBwcm90byAyIDAKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM1CiAgICAvLyBhc3NlcnQgc2VsZi51bml0YXJ5X3ByaWNlICE9IFVJbnQ2NCgwKQogICAgaW50IDAKICAgIGJ5dGUgInVuaXRhcnlfcHJpY2UiCiAgICBhcHBfZ2xvYmFsX2dldF9leAogICAgYXNzZXJ0IC8vIGNoZWNrIHVuaXRhcnlfcHJpY2UgZXhpc3RzCiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM2CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLnNlbmRlciA9PSBUeG4uc2VuZGVyCiAgICBmcmFtZV9kaWcgLTIKICAgIGd0eG5zIFNlbmRlcgogICAgdHhuIFNlbmRlcgogICAgPT0KICAgIGFzc2VydAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxMzcKICAgIC8vIGFzc2VydCBidXllcl90eG4ucmVjZWl2ZXIgPT0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcwogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBSZWNlaXZlcgogICAgZ2xvYmFsIEN1cnJlbnRBcHBsaWNhdGlvbkFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTM4CiAgICAvLyBhc3NlcnQgYnV5ZXJfdHhuLmFtb3VudCA9PSBzZWxmLnVuaXRhcnlfcHJpY2UgKiBxdWFudGl0eQogICAgZnJhbWVfZGlnIC0yCiAgICBndHhucyBBbW91bnQKICAgIGludCAwCiAgICBieXRlICJ1bml0YXJ5X3ByaWNlIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayB1bml0YXJ5X3ByaWNlIGV4aXN0cwogICAgZnJhbWVfZGlnIC0xCiAgICAqCiAgICA9PQogICAgYXNzZXJ0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MC0xNDQKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MQogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTQyCiAgICAvLyBhc3NldF9yZWNlaXZlcj1UeG4uc2VuZGVyLAogICAgdHhuIFNlbmRlcgogICAgZnJhbWVfZGlnIC0xCiAgICBpdHhuX2ZpZWxkIEFzc2V0QW1vdW50CiAgICBpdHhuX2ZpZWxkIEFzc2V0UmVjZWl2ZXIKICAgIGl0eG5fZmllbGQgWGZlckFzc2V0CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MAogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgaW50IGF4ZmVyCiAgICBpdHhuX2ZpZWxkIFR5cGVFbnVtCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE0MC0xNDQKICAgIC8vIGl0eG4uQXNzZXRUcmFuc2ZlcigKICAgIC8vICAgICB4ZmVyX2Fzc2V0PXNlbGYuYXNzZXRfaWQsCiAgICAvLyAgICAgYXNzZXRfcmVjZWl2ZXI9VHhuLnNlbmRlciwKICAgIC8vICAgICBhc3NldF9hbW91bnQ9cXVhbnRpdHksCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgcmV0c3ViCgoKLy8gc21hcnRfY29udHJhY3RzLm5mdF9tYXJrZXRwbGFjZS5jb250cmFjdC5OZnRNYXJrZXRwbGFjZS53aXRoZHJhd19hbmRfZGVsZXRlKCkgLT4gdWludDY0Ogp3aXRoZHJhd19hbmRfZGVsZXRlOgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxNzYtMTc3CiAgICAvLyBAYXJjNC5hYmltZXRob2QoYWxsb3dfYWN0aW9ucz1bIkRlbGV0ZUFwcGxpY2F0aW9uIl0pCiAgICAvLyBkZWYgd2l0aGRyYXdfYW5kX2RlbGV0ZShzZWxmKSAtPiBVSW50NjQ6CiAgICBwcm90byAwIDEKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc4CiAgICAvLyBhc3NlcnQgVHhuLnNlbmRlciA9PSBHbG9iYWwuY3JlYXRvcl9hZGRyZXNzCiAgICB0eG4gU2VuZGVyCiAgICBnbG9iYWwgQ3JlYXRvckFkZHJlc3MKICAgID09CiAgICBhc3NlcnQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTc5CiAgICAvLyBjb250cmFjdF9iYWxhbmNlID0gR2xvYmFsLmN1cnJlbnRfYXBwbGljYXRpb25fYWRkcmVzcy5iYWxhbmNlCiAgICBnbG9iYWwgQ3VycmVudEFwcGxpY2F0aW9uQWRkcmVzcwogICAgYWNjdF9wYXJhbXNfZ2V0IEFjY3RCYWxhbmNlCiAgICBhc3NlcnQgLy8gYWNjb3VudCBmdW5kZWQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgxLTE4NQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX2JlZ2luCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4MgogICAgLy8geGZlcl9hc3NldD1zZWxmLmFzc2V0X2lkLAogICAgaW50IDAKICAgIGJ5dGUgImFzc2V0X2lkIgogICAgYXBwX2dsb2JhbF9nZXRfZXgKICAgIGFzc2VydCAvLyBjaGVjayBhc3NldF9pZCBleGlzdHMKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgzCiAgICAvLyBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4NAogICAgLy8gYXNzZXRfY2xvc2VfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIGR1cAogICAgaXR4bl9maWVsZCBBc3NldENsb3NlVG8KICAgIGl0eG5fZmllbGQgQXNzZXRSZWNlaXZlcgogICAgaXR4bl9maWVsZCBYZmVyQXNzZXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgxCiAgICAvLyBpdHhuLkFzc2V0VHJhbnNmZXIoCiAgICBpbnQgYXhmZXIKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTgxLTE4NQogICAgLy8gaXR4bi5Bc3NldFRyYW5zZmVyKAogICAgLy8gICAgIHhmZXJfYXNzZXQ9c2VsZi5hc3NldF9pZCwKICAgIC8vICAgICBhc3NldF9yZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgLy8gICAgIGFzc2V0X2Nsb3NlX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODctMTkwCiAgICAvLyBpdHhuLlBheW1lbnQoCiAgICAvLyAgICAgcmVjZWl2ZXI9R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICAgICBjbG9zZV9yZW1haW5kZXJfdG89R2xvYmFsLmNyZWF0b3JfYWRkcmVzcywKICAgIC8vICkuc3VibWl0KCkKICAgIGl0eG5fYmVnaW4KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg4CiAgICAvLyByZWNlaXZlcj1HbG9iYWwuY3JlYXRvcl9hZGRyZXNzLAogICAgZ2xvYmFsIENyZWF0b3JBZGRyZXNzCiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjE4OQogICAgLy8gY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICBkdXAKICAgIGl0eG5fZmllbGQgQ2xvc2VSZW1haW5kZXJUbwogICAgaXR4bl9maWVsZCBSZWNlaXZlcgogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxODcKICAgIC8vIGl0eG4uUGF5bWVudCgKICAgIGludCBwYXkKICAgIGl0eG5fZmllbGQgVHlwZUVudW0KICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6MTg3LTE5MAogICAgLy8gaXR4bi5QYXltZW50KAogICAgLy8gICAgIHJlY2VpdmVyPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyAgICAgY2xvc2VfcmVtYWluZGVyX3RvPUdsb2JhbC5jcmVhdG9yX2FkZHJlc3MsCiAgICAvLyApLnN1Ym1pdCgpCiAgICBpdHhuX3N1Ym1pdAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weToxOTIKICAgIC8vIHJldHVybiBjb250cmFjdF9iYWxhbmNlCiAgICByZXRzdWIKCgovLyBzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLl9faW5pdF9fKCkgLT4gdm9pZDoKX19pbml0X186CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjUyCiAgICAvLyBkZWYgX19pbml0X18oc2VsZikgLT4gTm9uZToKICAgIHByb3RvIDAgMAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1MwogICAgLy8gc2VsZi5hc3NldF9pZCA9IFVJbnQ2NCgwKQogICAgYnl0ZSAiYXNzZXRfaWQiCiAgICBpbnQgMAogICAgYXBwX2dsb2JhbF9wdXQKICAgIC8vIHNtYXJ0X2NvbnRyYWN0cy9uZnRfbWFya2V0cGxhY2UvY29udHJhY3QucHk6NTQKICAgIC8vIHNlbGYudW5pdGFyeV9wcmljZSA9IFVJbnQ2NCgwKQogICAgYnl0ZSAidW5pdGFyeV9wcmljZSIKICAgIGludCAwCiAgICBhcHBfZ2xvYmFsX3B1dAogICAgLy8gc21hcnRfY29udHJhY3RzL25mdF9tYXJrZXRwbGFjZS9jb250cmFjdC5weTo1NQogICAgLy8gc2VsZi5ib290c3RyYXBwZWQgPSBGYWxzZQogICAgYnl0ZSAiYm9vdHN0cmFwcGVkIgogICAgaW50IDAKICAgIGFwcF9nbG9iYWxfcHV0CiAgICByZXRzdWIK", "clear": "I3ByYWdtYSB2ZXJzaW9uIDEwCgpzbWFydF9jb250cmFjdHMubmZ0X21hcmtldHBsYWNlLmNvbnRyYWN0Lk5mdE1hcmtldHBsYWNlLmNsZWFyX3N0YXRlX3Byb2dyYW06CiAgICAvLyBzbWFydF9jb250cmFjdHMvbmZ0X21hcmtldHBsYWNlL2NvbnRyYWN0LnB5OjMwCiAgICAvLyBjbGFzcyBOZnRNYXJrZXRwbGFjZShhcmM0LkFSQzRDb250cmFjdCk6CiAgICBpbnQgMQogICAgcmV0dXJuCg==" }, "state": { diff --git a/projects/orakle-nft-marketplace-app-frontend/src/methods.ts b/projects/orakle-nft-marketplace-app-frontend/src/methods.ts index 57f4d57..14c0c8e 100644 --- a/projects/orakle-nft-marketplace-app-frontend/src/methods.ts +++ b/projects/orakle-nft-marketplace-app-frontend/src/methods.ts @@ -1,10 +1,30 @@ /* eslint-disable no-console */ import * as algokit from '@algorandfoundation/algokit-utils' -import algosdk from 'algosdk' import { NftMarketplaceClient } from './contracts/NftMarketplace' import { NftMarketplaceListClient } from './contracts/NftMarketplaceList' import { marketplaceListAppId } from './utils/marketplaceListAppId' +/* +=== 먼저 읽고 진행해주세요!! === +methods.ts 파일은 디지털 마켓플레이스 앱을 생성하고 호출하는 여러 메서드들을 정의하는 파일입니다. +이 파일에는 3개의 함수가 정의되어 있습니다. +1. create +2. buy +3. deleteApp + +Home.tsx 파일을 보면 상황에 따라 각 메서드들을 MethodCall.tsx 컴포넌트에 전달해 호출하고 있습니다. +또한 Home.tsx에서 여러분들이 만든 dmClient가 디지털 마켓플레이스의 앱 클라이언트고 이 파일에 있는 3개의 +함수들의 전달값으로 사용되고 있습니다. + +시작하기 전 Home.tsx 라인 16을 보시면 아래 코드가 있습니다. +- AlgokitConfig.configure({ populateAppCallResources: true }) + +이 코드 하나로 모든 앱 호출시 필요한 레퍼런스들을 자동으로 기입해주는 기능을 활성화 할 수 있습니다. +즉, 수동적으로 populateAppResources를 설정할 필요가 없습니다! (이거 직접 하게 만들려다가 참았어요 ^^) + +이 파일에는 문제 6부터 9까지 총 4문제가 있습니다. 아래 설명들을 자세히 읽고 문제를 풀어주세요! +*/ + export function create( algorand: algokit.AlgorandClient, nftmClient: NftMarketplaceClient, @@ -16,8 +36,35 @@ export function create( ) { return async () => { console.log('creating app') + console.log('nftmClient', nftmClient) + + /* + 문제 6 + 문제1에서 생성한 dmClient를 사용하여 앱을 배포하세요. + + 이때 `deploy`가 아닌 `create` 메서드를 사용해서 배포하세요. + `deploy`는 스마트계약이 이미 배포 되있는지 확인하고 배포 되어 있다면 다시 배포하지 않습니다. 과제를 풀때 항상 새로 + 배포하는게 편하기 때문에 스크립트가 실행될때마다 배포하는 `create` 메서드를 사용해주세요. + + 또한 디지털 마켓플레이스에 create 메서드를 따로 구현하지 않았기 때문에 기본적으로 제공되늗 bare create 메서드를 사용합니다. + + 힌트: https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#create-calls + */ const createResult = await nftmClient.create.bare() + /* + 문제 7 + 부트스트랩 메서드는 앱이 필요한 미니멈 밸런스를 지급하고 앱이 판매할 NFT 에셋에 옵트인하는 메서드입니다. + 앱이 판매할 준비가 되도록 Bootstrap 메서드를 호출하세요. + + 부트스트랩 메서드는 호출 시 판매할 NFT에 옵트인하는 inner transaction이 있습니다. + 따라서 부트스트랩 메서드 호출자가 inner transaction의 트랜잭션 비용을 내야합니다. + 이 부분은 mbrTxn안에 extraFee를 통해서 설정을 해주면 됩니다. 이때 extraFee는 AlgoAmount 데이터타입을 받습니다!! + 알고랜드의 트랜잭션 비용은 0.001 Algos입니다. + + 힌트1: AlgoAmount 설정하는 방법: https://github.com/algorandfoundation/algokit-utils-ts/blob/e9682db133fab42627648ac2f779cd91f3e6cd21/docs/capabilities/amount.md#creating-an-algoamount + 힌트2: 앱 클라이언트 메서드 호출때 메서드 전달값 넣는법: https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#abi-arguments + */ const mbrTxn = await algorand.transactions.payment({ sender, receiver: createResult.appAddress, @@ -25,6 +72,14 @@ export function create( extraFee: algokit.algos(0.001), }) + // 문제 7 시작 + await nftmClient.bootstrap({ + asset: assetBeingSold, + unitaryPrice, + mbrPay: mbrTxn, + }) + // 문제 7 끝 + const sendAssetToSell = { assetId: assetBeingSold, sender, @@ -32,14 +87,8 @@ export function create( amount: quantity, } - const result = await algorand + await algorand .newGroup() - .addMethodCall({ - sender: sender, - appId: BigInt(createResult.appId), - method: nftmClient.appClient.getABIMethod('bootstrap')!, - args: [assetBeingSold, unitaryPrice, mbrTxn], - }) .addAssetTransfer(sendAssetToSell) .addMethodCall({ sender: sender, @@ -48,8 +97,6 @@ export function create( args: [createResult.appId], }) .execute() - - console.log('List Result: ', result.returns![1].returnValue) } } @@ -63,6 +110,19 @@ export function buy( unitaryPrice: bigint, ) { return async () => { + /* + 문제 8 + 밑에 `buyerTxn` 결제 트랜잭션를 buy 메서드의 전달값으로 넣어 어토믹 트랜잭션으로 동시에 호출하세요. + + buy 메서드는 호출 시 스마트 계약에 있는 NFT를 구매자 지갑으로 보내주는 inner transaction이 있습니다. + 따라서 buy 메서드 호출자가 inner transaction의 트랜잭션 비용을 내야합니다. + 이 부분은 buyerTxn안에 extraFee를 통해서 설정을 해주면 됩니다. 이때 extraFee는 AlgoAmount 데이터타입을 받습니다!! + 알고랜드의 트랜잭션 비용은 0.001 Algos입니다. + + 힌트1: AlgoAmount 설정하는 방법: https://github.com/algorandfoundation/algokit-utils-ts/blob/e9682db133fab42627648ac2f779cd91f3e6cd21/docs/capabilities/amount.md#creating-an-algoamount + 힌트2: 앱 클라이언트 메서드 호출때 메서드 전달값 넣는법: https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#abi-arguments + */ + const buyerTxn = await algorand.transactions.payment({ sender, receiver: appAddress, @@ -75,21 +135,15 @@ export function buy( console.log(`${sender}가 이미 에셋에 옵트인 되어있어요! 현재 보유한 티켓 수: ${assetInfo.balance}개`) } catch (e) { console.log(`${sender}가 에셋에 옵트인이 안 되어있어요. 옵트인 진행할게요~`) - // 구매자가 NFT에 옵트인 - const appId = (await nftmClient.appClient.getAppReference()).appId - await algorand - .newGroup() - .addAssetOptIn({ - sender: sender, - assetId: assetId, - }) - .addMethodCall({ - sender: sender, - appId: BigInt(appId), - method: nftmClient.appClient.getABIMethod('buy')!, - args: [buyerTxn, quantity], - }) - .execute() + + const assetOptInTxn = await algorand.transactions.assetOptIn({ + sender, + assetId, + }) + // 문제 8 시작 + await nftmClient.compose().addTransaction(assetOptInTxn).buy({ buyerTxn: buyerTxn, quantity }).execute() + // 문제 8 끝 + console.log(`${sender}가 에셋에 옵트인 완료했어요!`) return } @@ -102,32 +156,42 @@ export function buy( } } -export function deleteApp( - algorand: algokit.AlgorandClient, - nftmClient: NftMarketplaceClient, - listClient: NftMarketplaceListClient, - sender: string, - appId: number, -) { +export function deleteApp(nftmClient: NftMarketplaceClient, listClient: NftMarketplaceListClient, appId: number) { return async () => { console.log('deleting app') - await algorand - .newGroup() - .addMethodCall({ - sender: sender, - appId: BigInt(appId), - method: nftmClient.appClient.getABIMethod('withdraw_and_delete')!, - args: [], - extraFee: algokit.algos(0.003), - onComplete: algosdk.OnApplicationComplete.DeleteApplicationOC, - }) - .addMethodCall({ - sender: sender, - appId: BigInt(marketplaceListAppId), - method: listClient.appClient.getABIMethod('remove_marketplace_from_list')!, - args: [appId], - }) - .execute() + /* + 문제 9 + 앱을 삭제하고 수익금을 회수하는 withdrawAndDelete 메서드를 호출하세요. + + withdrawAndDelete 메서드는 OnComplete Actions가 DeleteApplication으로 설정된 특별한 메서드입니다. + 앱 클라이언트에는 delete라는 property가 있습니다. 이 delete property에 withdrawAndDelete 메서드가 있으니 이 메서드를 호출하시면 됩니다. + + 앱 클라이언트로 withdrawAndDelete 같은 메서드를 호출할때 전달값을 두개 넣을 수 있습니다. + 1. ABI Arguments: 스마트계약 메서드 호출시 전달값을 넣는 곳입니다. + 2. Additional Parameters: 앱 클라이언트 메서드 호출시 추가적인 설정을 넣는 곳입니다. + + abi argument: + withdrawAndDelete는 전닯값이 필요없는 메서드입니다. 따라서 빈 객체를 넣어주세요. + + additional parameters: + withdrawAndDelete는 2개의 inner txn를 보냅니다. + 1. 수익금 판매자에게 송금 + 2. 잔여 nft 송금 + 따라서 호출시 sendParams 안에 추가 fee 설정을 해야합니다. + - fee: sendParams 객체 안에 fee를 0.003 Algos로 설정해야합니다. + + 힌트1: 앱클라이언트로 앱을 delete 하는법 - https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#update-and-delete-calls + 힌트2: 앱 클라이언트 메서드 호출때 메서드 전달값 넣는법: https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#abi-arguments + 힌트3: additional parameters에 extra fee 설정하는 방법: https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#additional-parameters + 힌트4: AlgoAmount 설정하는 방법: https://github.com/algorandfoundation/algokit-utils-ts/blob/e9682db133fab42627648ac2f779cd91f3e6cd21/docs/capabilities/amount.md#creating-an-algoamount + 힌트5: 다 시도해보고 모르겠을때 보세요!: https://github.com/algorand-devrel/blockchain-valley-session-2/blob/df789308e76a5a6cb3c815b256779fb197add8fd/projects/coding-assignment/smart_contracts/digital_marketplace/deploy-config.ts#L70C1-L74C4 + */ + + // 문제 9 시작 + await nftmClient.delete.withdrawAndDelete({}, { sendParams: { fee: algokit.algos(0.003) } }) + // 문제 9 끝 + + await listClient.removeMarketplaceFromList({ appId: BigInt(appId) }) } } diff --git a/projects/orakle-nft-marketplace-app-frontend/src/utils/getCurrentNftmClient.ts b/projects/orakle-nft-marketplace-app-frontend/src/utils/getCurrentNftmClient.ts new file mode 100644 index 0000000..4b472b0 --- /dev/null +++ b/projects/orakle-nft-marketplace-app-frontend/src/utils/getCurrentNftmClient.ts @@ -0,0 +1,49 @@ +import { AlgorandClient } from '@algorandfoundation/algokit-utils' +import { TransactionSigner } from 'algosdk' +import { NftMarketplaceClient } from '../contracts/NftMarketplace' + +export function getCurrentNftmClient( + algorandClient: AlgorandClient, + currentAppId: bigint | number, + activeAddress: string, + signer: TransactionSigner, +): NftMarketplaceClient { + /* + 문제 5 + 디지털 마켓플레이스 앱 클라이언트 인스턴스를 생성하세요. + + 앱 클라이언트는 쉽고 간편하게 스마트계약을 배포 및 호출할 수 있도록 해주는 클라이언트입니다. + 앱 클라이언트 인스턴스를 만드는 방법은 두가지가 있습니다. + 1. resolve by creator and name: 배포자와 앱 이름으로 앱 클라이언트를 찾아서 생성 + 2. resolve by id: 앱 ID로 앱 클라이언트를 찾아서 생성 + + 둘 다 사용 가능하지만 각각 장단점이 있어요. + creator and name + - 장점: 앱 이름과 배포자만 알면 앱 아이디를 하드코드할 필요가 없고 개발 중 여러 네트워크에서 자동적으로 앱 아이디를 찾아주기 때문에 편리합니다. + - 단점: indexer가 필요하기 때문에 indexer API 설정을 해야합니다. + + id + - 장점: indexer가 필요없어서 가볍게 앱 클라이언트를 생성할 수 있습니다. + - 단점: 앱 아이디를 알아야하기 때문에 네트워크가 바뀔때 코드를 바꿔줘야할 수 있습니다. + + 주목!!! + - 이 파일 맨 위에 이 코드를 복붙해 마켓플레이스 앱 클라이언트 class를 import하세요: import { DigitalMarketplaceClient } from './contracts/DigitalMarketplace' + - 여기서는 resolve by id를 사용해주세요! + - sender값에는 { addr: activeAddress!, signer }를 복붙해주세요. useWallet를 통해 현재 연결된 지갑 주소와 서명자를 사용하는 코드입니다. + + 힌트: https://github.com/algorandfoundation/algokit-client-generator-ts/blob/main/docs/usage.md#creating-an-application-client-instance + */ + + // 문제 5 시작 + const nftmClient = new NftMarketplaceClient( + { + resolveBy: 'id', + id: currentAppId, + sender: { addr: activeAddress, signer }, + }, + algorandClient.client.algod, + ) + // 문제 5 끝 + + return nftmClient +} diff --git a/projects/orakle-nft-marketplace-app-frontend/src/utils/marketplaceListAppId.ts b/projects/orakle-nft-marketplace-app-frontend/src/utils/marketplaceListAppId.ts index 4788432..dc8f941 100644 --- a/projects/orakle-nft-marketplace-app-frontend/src/utils/marketplaceListAppId.ts +++ b/projects/orakle-nft-marketplace-app-frontend/src/utils/marketplaceListAppId.ts @@ -1 +1 @@ -export const marketplaceListAppId = 670026211 +export const marketplaceListAppId = 1018