azimuth-hs (empty) → 0.1.0
raw patch · 18 files changed
+1663/−0 lines, 18 filesdep +azimuth-hsdep +basedep +data-default-class
Dependencies added: azimuth-hs, base, data-default-class, exceptions, haskoin-core, hspec, memory, mtl, shelly, text, urbit-hob, web3
Files
- CHANGELOG +8/−0
- LICENSE +373/−0
- azimuth-hs.cabal +91/−0
- etc/azimuth.json +1/−0
- etc/ecliptic.json +1/−0
- lib/Network/Web3/Provider/Extended.hs +47/−0
- lib/Urbit/Azimuth.hs +20/−0
- lib/Urbit/Azimuth/Account.hs +49/−0
- lib/Urbit/Azimuth/Azimuth.hs +188/−0
- lib/Urbit/Azimuth/Azimuth/Internal.hs +17/−0
- lib/Urbit/Azimuth/Contract.hs +68/−0
- lib/Urbit/Azimuth/Ecliptic.hs +295/−0
- lib/Urbit/Azimuth/Ecliptic/Internal.hs +17/−0
- lib/Urbit/Azimuth/Point.hs +228/−0
- lib/Urbit/Azimuth/Transaction.hs +7/−0
- lib/Urbit/Ob/Extended.hs +47/−0
- test/Doc.hs +39/−0
- test/Main.hs +167/−0
+ CHANGELOG view
@@ -0,0 +1,8 @@+# Changelog++- 0.1.0 (2020-07-14)+ * Initial release.++ Supports the Azimuth and Ecliptic contracts, basic account management,+ and basic transaction submission.+
+ LICENSE view
@@ -0,0 +1,373 @@+Mozilla Public License Version 2.0+==================================++1. Definitions+--------------++1.1. "Contributor"+ means each individual or legal entity that creates, contributes to+ the creation of, or owns Covered Software.++1.2. "Contributor Version"+ means the combination of the Contributions of others (if any) used+ by a Contributor and that particular Contributor's Contribution.++1.3. "Contribution"+ means Covered Software of a particular Contributor.++1.4. "Covered Software"+ means Source Code Form to which the initial Contributor has attached+ the notice in Exhibit A, the Executable Form of such Source Code+ Form, and Modifications of such Source Code Form, in each case+ including portions thereof.++1.5. "Incompatible With Secondary Licenses"+ means++ (a) that the initial Contributor has attached the notice described+ in Exhibit B to the Covered Software; or++ (b) that the Covered Software was made available under the terms of+ version 1.1 or earlier of the License, but not also under the+ terms of a Secondary License.++1.6. "Executable Form"+ means any form of the work other than Source Code Form.++1.7. "Larger Work"+ means a work that combines Covered Software with other material, in+ a separate file or files, that is not Covered Software.++1.8. "License"+ means this document.++1.9. "Licensable"+ means having the right to grant, to the maximum extent possible,+ whether at the time of the initial grant or subsequently, any and+ all of the rights conveyed by this License.++1.10. "Modifications"+ means any of the following:++ (a) any file in Source Code Form that results from an addition to,+ deletion from, or modification of the contents of Covered+ Software; or++ (b) any new file in Source Code Form that contains any Covered+ Software.++1.11. "Patent Claims" of a Contributor+ means any patent claim(s), including without limitation, method,+ process, and apparatus claims, in any patent Licensable by such+ Contributor that would be infringed, but for the grant of the+ License, by the making, using, selling, offering for sale, having+ made, import, or transfer of either its Contributions or its+ Contributor Version.++1.12. "Secondary License"+ means either the GNU General Public License, Version 2.0, the GNU+ Lesser General Public License, Version 2.1, the GNU Affero General+ Public License, Version 3.0, or any later versions of those+ licenses.++1.13. "Source Code Form"+ means the form of the work preferred for making modifications.++1.14. "You" (or "Your")+ means an individual or a legal entity exercising rights under this+ License. For legal entities, "You" includes any entity that+ controls, is controlled by, or is under common control with You. For+ purposes of this definition, "control" means (a) the power, direct+ or indirect, to cause the direction or management of such entity,+ whether by contract or otherwise, or (b) ownership of more than+ fifty percent (50%) of the outstanding shares or beneficial+ ownership of such entity.++2. License Grants and Conditions+--------------------------------++2.1. Grants++Each Contributor hereby grants You a world-wide, royalty-free,+non-exclusive license:++(a) under intellectual property rights (other than patent or trademark)+ Licensable by such Contributor to use, reproduce, make available,+ modify, display, perform, distribute, and otherwise exploit its+ Contributions, either on an unmodified basis, with Modifications, or+ as part of a Larger Work; and++(b) under Patent Claims of such Contributor to make, use, sell, offer+ for sale, have made, import, and otherwise transfer either its+ Contributions or its Contributor Version.++2.2. Effective Date++The licenses granted in Section 2.1 with respect to any Contribution+become effective for each Contribution on the date the Contributor first+distributes such Contribution.++2.3. Limitations on Grant Scope++The licenses granted in this Section 2 are the only rights granted under+this License. No additional rights or licenses will be implied from the+distribution or licensing of Covered Software under this License.+Notwithstanding Section 2.1(b) above, no patent license is granted by a+Contributor:++(a) for any code that a Contributor has removed from Covered Software;+ or++(b) for infringements caused by: (i) Your and any other third party's+ modifications of Covered Software, or (ii) the combination of its+ Contributions with other software (except as part of its Contributor+ Version); or++(c) under Patent Claims infringed by Covered Software in the absence of+ its Contributions.++This License does not grant any rights in the trademarks, service marks,+or logos of any Contributor (except as may be necessary to comply with+the notice requirements in Section 3.4).++2.4. Subsequent Licenses++No Contributor makes additional grants as a result of Your choice to+distribute the Covered Software under a subsequent version of this+License (see Section 10.2) or under the terms of a Secondary License (if+permitted under the terms of Section 3.3).++2.5. Representation++Each Contributor represents that the Contributor believes its+Contributions are its original creation(s) or it has sufficient rights+to grant the rights to its Contributions conveyed by this License.++2.6. Fair Use++This License is not intended to limit any rights You have under+applicable copyright doctrines of fair use, fair dealing, or other+equivalents.++2.7. Conditions++Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted+in Section 2.1.++3. Responsibilities+-------------------++3.1. Distribution of Source Form++All distribution of Covered Software in Source Code Form, including any+Modifications that You create or to which You contribute, must be under+the terms of this License. You must inform recipients that the Source+Code Form of the Covered Software is governed by the terms of this+License, and how they can obtain a copy of this License. You may not+attempt to alter or restrict the recipients' rights in the Source Code+Form.++3.2. Distribution of Executable Form++If You distribute Covered Software in Executable Form then:++(a) such Covered Software must also be made available in Source Code+ Form, as described in Section 3.1, and You must inform recipients of+ the Executable Form how they can obtain a copy of such Source Code+ Form by reasonable means in a timely manner, at a charge no more+ than the cost of distribution to the recipient; and++(b) You may distribute such Executable Form under the terms of this+ License, or sublicense it under different terms, provided that the+ license for the Executable Form does not attempt to limit or alter+ the recipients' rights in the Source Code Form under this License.++3.3. Distribution of a Larger Work++You may create and distribute a Larger Work under terms of Your choice,+provided that You also comply with the requirements of this License for+the Covered Software. If the Larger Work is a combination of Covered+Software with a work governed by one or more Secondary Licenses, and the+Covered Software is not Incompatible With Secondary Licenses, this+License permits You to additionally distribute such Covered Software+under the terms of such Secondary License(s), so that the recipient of+the Larger Work may, at their option, further distribute the Covered+Software under the terms of either this License or such Secondary+License(s).++3.4. Notices++You may not remove or alter the substance of any license notices+(including copyright notices, patent notices, disclaimers of warranty,+or limitations of liability) contained within the Source Code Form of+the Covered Software, except that You may alter any license notices to+the extent required to remedy known factual inaccuracies.++3.5. Application of Additional Terms++You may choose to offer, and to charge a fee for, warranty, support,+indemnity or liability obligations to one or more recipients of Covered+Software. However, You may do so only on Your own behalf, and not on+behalf of any Contributor. You must make it absolutely clear that any+such warranty, support, indemnity, or liability obligation is offered by+You alone, and You hereby agree to indemnify every Contributor for any+liability incurred by such Contributor as a result of warranty, support,+indemnity or liability terms You offer. You may include additional+disclaimers of warranty and limitations of liability specific to any+jurisdiction.++4. Inability to Comply Due to Statute or Regulation+---------------------------------------------------++If it is impossible for You to comply with any of the terms of this+License with respect to some or all of the Covered Software due to+statute, judicial order, or regulation then You must: (a) comply with+the terms of this License to the maximum extent possible; and (b)+describe the limitations and the code they affect. Such description must+be placed in a text file included with all distributions of the Covered+Software under this License. Except to the extent prohibited by statute+or regulation, such description must be sufficiently detailed for a+recipient of ordinary skill to be able to understand it.++5. Termination+--------------++5.1. The rights granted under this License will terminate automatically+if You fail to comply with any of its terms. However, if You become+compliant, then the rights granted under this License from a particular+Contributor are reinstated (a) provisionally, unless and until such+Contributor explicitly and finally terminates Your grants, and (b) on an+ongoing basis, if such Contributor fails to notify You of the+non-compliance by some reasonable means prior to 60 days after You have+come back into compliance. Moreover, Your grants from a particular+Contributor are reinstated on an ongoing basis if such Contributor+notifies You of the non-compliance by some reasonable means, this is the+first time You have received notice of non-compliance with this License+from such Contributor, and You become compliant prior to 30 days after+Your receipt of the notice.++5.2. If You initiate litigation against any entity by asserting a patent+infringement claim (excluding declaratory judgment actions,+counter-claims, and cross-claims) alleging that a Contributor Version+directly or indirectly infringes any patent, then the rights granted to+You by any and all Contributors for the Covered Software under Section+2.1 of this License shall terminate.++5.3. In the event of termination under Sections 5.1 or 5.2 above, all+end user license agreements (excluding distributors and resellers) which+have been validly granted by You or Your distributors under this License+prior to termination shall survive termination.++************************************************************************+* *+* 6. Disclaimer of Warranty *+* ------------------------- *+* *+* Covered Software is provided under this License on an "as is" *+* basis, without warranty of any kind, either expressed, implied, or *+* statutory, including, without limitation, warranties that the *+* Covered Software is free of defects, merchantable, fit for a *+* particular purpose or non-infringing. The entire risk as to the *+* quality and performance of the Covered Software is with You. *+* Should any Covered Software prove defective in any respect, You *+* (not any Contributor) assume the cost of any necessary servicing, *+* repair, or correction. This disclaimer of warranty constitutes an *+* essential part of this License. No use of any Covered Software is *+* authorized under this License except under this disclaimer. *+* *+************************************************************************++************************************************************************+* *+* 7. Limitation of Liability *+* -------------------------- *+* *+* Under no circumstances and under no legal theory, whether tort *+* (including negligence), contract, or otherwise, shall any *+* Contributor, or anyone who distributes Covered Software as *+* permitted above, be liable to You for any direct, indirect, *+* special, incidental, or consequential damages of any character *+* including, without limitation, damages for lost profits, loss of *+* goodwill, work stoppage, computer failure or malfunction, or any *+* and all other commercial damages or losses, even if such party *+* shall have been informed of the possibility of such damages. This *+* limitation of liability shall not apply to liability for death or *+* personal injury resulting from such party's negligence to the *+* extent applicable law prohibits such limitation. Some *+* jurisdictions do not allow the exclusion or limitation of *+* incidental or consequential damages, so this exclusion and *+* limitation may not apply to You. *+* *+************************************************************************++8. Litigation+-------------++Any litigation relating to this License may be brought only in the+courts of a jurisdiction where the defendant maintains its principal+place of business and such litigation shall be governed by laws of that+jurisdiction, without reference to its conflict-of-law provisions.+Nothing in this Section shall prevent a party's ability to bring+cross-claims or counter-claims.++9. Miscellaneous+----------------++This License represents the complete agreement concerning the subject+matter hereof. If any provision of this License is held to be+unenforceable, such provision shall be reformed only to the extent+necessary to make it enforceable. Any law or regulation which provides+that the language of a contract shall be construed against the drafter+shall not be used to construe this License against a Contributor.++10. Versions of the License+---------------------------++10.1. New Versions++Mozilla Foundation is the license steward. Except as provided in Section+10.3, no one other than the license steward has the right to modify or+publish new versions of this License. Each version will be given a+distinguishing version number.++10.2. Effect of New Versions++You may distribute the Covered Software under the terms of the version+of the License under which You originally received the Covered Software,+or under the terms of any subsequent version published by the license+steward.++10.3. Modified Versions++If you create software not governed by this License, and you want to+create a new license for such software, you may create and use a+modified version of this License if you rename the license and remove+any references to the name of the license steward (except to note that+such modified license differs from this License).++10.4. Distributing Source Code Form that is Incompatible With Secondary+Licenses++If You choose to distribute Source Code Form that is Incompatible With+Secondary Licenses under the terms of this version of the License, the+notice described in Exhibit B of this License must be attached.++Exhibit A - Source Code Form License Notice+-------------------------------------------++ This Source Code Form is subject to the terms of the Mozilla Public+ License, v. 2.0. If a copy of the MPL was not distributed with this+ file, You can obtain one at http://mozilla.org/MPL/2.0/.++If it is not possible or desirable to put the notice in a particular+file, then You may include the notice in a location (such as a LICENSE+file in a relevant directory) where a recipient would be likely to look+for such a notice.++You may add additional accurate notices of copyright ownership.++Exhibit B - "Incompatible With Secondary Licenses" Notice+---------------------------------------------------------++ This Source Code Form is "Incompatible With Secondary Licenses", as+ defined by the Mozilla Public License, v. 2.0.
+ azimuth-hs.cabal view
@@ -0,0 +1,91 @@+cabal-version: 2.4+name: azimuth-hs+version: 0.1.0+synopsis: Interact with Azimuth from Haskell+description: Haskell bindings for Azimuth (https://github.com/urbit/azimuth)+homepage: https://github.com/urbit/azimuth-hs+category: Urbit+license: MPL-2.0+license-file: LICENSE+author: Brendan Hay,+ Jared Tobin+maintainer: jared@jtobin.io+copyright: 2020 Brendan Hay+extra-source-files:+ CHANGELOG++data-files:+ etc/azimuth.json+ etc/ecliptic.json++source-repository head+ type: git+ location: https://github.com/urbit/azimuth-hs++common base+ default-language: Haskell2010+ ghc-options:+ -Weverything -Wno-safe -Wno-unsafe -Wno-missing-local-signatures+ -Wno-missing-import-lists -Wno-implicit-prelude+ build-depends:+ base >= 4.12 && < 5++library+ import: base+ hs-source-dirs: lib+ build-depends:+ data-default-class == 0.1.2.0+ , exceptions >= 0.10+ , haskoin-core == 0.13.4+ , memory >= 0.15+ , mtl >= 2.2+ , text >= 1.2+ , urbit-hob >= 0.3+ , web3 == 0.9.1.0++ exposed-modules:+ Urbit.Azimuth+ Urbit.Azimuth.Account+ Urbit.Azimuth.Azimuth+ Urbit.Azimuth.Azimuth.Internal+ Urbit.Azimuth.Contract+ Urbit.Azimuth.Ecliptic+ Urbit.Azimuth.Ecliptic.Internal+ Urbit.Azimuth.Point+ Urbit.Azimuth.Transaction++ other-modules:+ Network.Web3.Provider.Extended+ Urbit.Ob.Extended++Test-suite tests+ import: base+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Main.hs+ default-language: Haskell2010+ ghc-options:+ -rtsopts -Wno-monomorphism-restriction -Wno-unused-do-bind+ -Wno-incomplete-uni-patterns -Wno-missing-export-lists+ -Wno-unused-local-binds+ build-depends:+ azimuth-hs+ , hspec+ , shelly+ , text+ , urbit-hob++Test-suite doctests+ import: base+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Doc.hs+ default-language: Haskell2010+ ghc-options:+ -rtsopts -Wno-monomorphism-restriction -Wno-unused-do-bind+ -Wno-incomplete-uni-patterns -Wno-missing-export-lists+ -Wno-unused-local-binds+ build-depends:+ azimuth-hs+ , urbit-hob+
+ etc/azimuth.json view
@@ -0,0 +1,1 @@+[{"constant":true,"inputs":[{"name":"","type":"uint32"},{"name":"","type":"uint32"}],"name":"escapeRequestsIndexes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_whose","type":"address"}],"name":"getOwnedPoints","outputs":[{"name":"ownedPoints","type":"uint32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"votingFor","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint32"}],"name":"rights","outputs":[{"name":"owner","type":"address"},{"name":"managementProxy","type":"address"},{"name":"spawnProxy","type":"address"},{"name":"votingProxy","type":"address"},{"name":"transferProxy","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"transferringFor","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_sponsor","type":"uint32"}],"name":"isSponsor","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getManagementProxy","outputs":[{"name":"manager","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getContinuityNumber","outputs":[{"name":"continuityNumber","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint32"},{"name":"","type":"uint256"}],"name":"sponsoring","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_whose","type":"address"}],"name":"getOwnedPointCount","outputs":[{"name":"count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"doEscape","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_whose","type":"address"},{"name":"_index","type":"uint256"}],"name":"getOwnedPointAtIndex","outputs":[{"name":"point","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getTransferProxy","outputs":[{"name":"transferProxy","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_proxy","type":"address"}],"name":"isSpawnProxy","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"pointsOwnedBy","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"operators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getSpawnCount","outputs":[{"name":"spawnCount","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_proxy","type":"address"}],"name":"setSpawnProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_proxy","type":"address"}],"name":"setTransferProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint32"},{"name":"","type":"uint32"}],"name":"sponsoringIndexes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_proxy","type":"address"}],"name":"isTransferProxy","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getVotingProxy","outputs":[{"name":"voter","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_proxy","type":"address"}],"name":"isManagementProxy","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint32"}],"name":"votingForIndexes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"isLive","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_sponsor","type":"uint32"}],"name":"getEscapeRequests","outputs":[{"name":"requests","type":"uint32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getSponsor","outputs":[{"name":"sponsor","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_sponsor","type":"uint32"}],"name":"getEscapeRequestsCount","outputs":[{"name":"count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint32"}],"name":"pointOwnerIndexes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_proxy","type":"address"}],"name":"getManagerFor","outputs":[{"name":"mfor","type":"uint32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint32"}],"name":"managerForIndexes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"managerFor","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"isActive","outputs":[{"name":"equals","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getOwner","outputs":[{"name":"owner","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint32"}],"name":"points","outputs":[{"name":"encryptionKey","type":"bytes32"},{"name":"authenticationKey","type":"bytes32"},{"name":"hasSponsor","type":"bool"},{"name":"active","type":"bool"},{"name":"escapeRequested","type":"bool"},{"name":"sponsor","type":"uint32"},{"name":"escapeRequestedTo","type":"uint32"},{"name":"cryptoSuiteVersion","type":"uint32"},{"name":"keyRevisionNumber","type":"uint32"},{"name":"continuityNumber","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_proxy","type":"address"}],"name":"getSpawningForCount","outputs":[{"name":"count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"hasBeenLinked","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_who","type":"address"}],"name":"canTransfer","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint32"}],"name":"spawningForIndexes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"hasSponsor","outputs":[{"name":"has","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"activatePoint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getSpawned","outputs":[{"name":"spawned","type":"uint32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_proxy","type":"address"}],"name":"setManagementProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_who","type":"address"}],"name":"canSpawnAs","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getKeyRevisionNumber","outputs":[{"name":"revision","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_who","type":"address"}],"name":"canManage","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_proxy","type":"address"}],"name":"getTransferringFor","outputs":[{"name":"tfor","type":"uint32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getPointSize","outputs":[{"name":"_size","type":"uint8"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"_sponsor","type":"uint32"}],"name":"getSponsoringCount","outputs":[{"name":"count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_proxy","type":"address"}],"name":"getSpawningFor","outputs":[{"name":"sfor","type":"uint32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"isEscaping","outputs":[{"name":"escaping","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint32"},{"name":"","type":"uint256"}],"name":"escapeRequests","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_proxy","type":"address"}],"name":"setVotingProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_sponsor","type":"uint32"}],"name":"getSponsoring","outputs":[{"name":"sponsees","type":"uint32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_sponsor","type":"uint32"}],"name":"setEscapeRequest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_operator","type":"address"}],"name":"isOperator","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_who","type":"address"}],"name":"canVoteAs","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_primary","type":"string"},{"name":"_secondary","type":"string"},{"name":"_tertiary","type":"string"}],"name":"setDnsDomains","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"loseSponsor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_operator","type":"address"},{"name":"_approved","type":"bool"}],"name":"setOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"registerSpawned","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getKeys","outputs":[{"name":"crypt","type":"bytes32"},{"name":"auth","type":"bytes32"},{"name":"suite","type":"uint32"},{"name":"revision","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"cancelEscape","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_address","type":"address"}],"name":"isOwner","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_proxy","type":"address"}],"name":"getManagerForCount","outputs":[{"name":"count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint32"}],"name":"transferringForIndexes","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_proxy","type":"address"}],"name":"getVotingFor","outputs":[{"name":"vfor","type":"uint32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"spawningFor","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_proxy","type":"address"}],"name":"getTransferringForCount","outputs":[{"name":"count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_proxy","type":"address"}],"name":"isVotingProxy","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getPrefix","outputs":[{"name":"prefix","type":"uint16"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"dnsDomains","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"incrementContinuityNumber","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getSpawnProxy","outputs":[{"name":"spawnProxy","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"}],"name":"getEscapeRequest","outputs":[{"name":"escape","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_encryptionKey","type":"bytes32"},{"name":"_authenticationKey","type":"bytes32"},{"name":"_cryptoSuiteVersion","type":"uint32"}],"name":"setKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_proxy","type":"address"}],"name":"getVotingForCount","outputs":[{"name":"count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_sponsor","type":"uint32"}],"name":"isRequestingEscapeTo","outputs":[{"name":"equals","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":true,"name":"owner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"}],"name":"Activated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"prefix","type":"uint32"},{"indexed":true,"name":"child","type":"uint32"}],"name":"Spawned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":true,"name":"sponsor","type":"uint32"}],"name":"EscapeRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":true,"name":"sponsor","type":"uint32"}],"name":"EscapeCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":true,"name":"sponsor","type":"uint32"}],"name":"EscapeAccepted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":true,"name":"sponsor","type":"uint32"}],"name":"LostSponsor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":false,"name":"encryptionKey","type":"bytes32"},{"indexed":false,"name":"authenticationKey","type":"bytes32"},{"indexed":false,"name":"cryptoSuiteVersion","type":"uint32"},{"indexed":false,"name":"keyRevisionNumber","type":"uint32"}],"name":"ChangedKeys","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":false,"name":"number","type":"uint32"}],"name":"BrokeContinuity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":true,"name":"spawnProxy","type":"address"}],"name":"ChangedSpawnProxy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":true,"name":"transferProxy","type":"address"}],"name":"ChangedTransferProxy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":true,"name":"managementProxy","type":"address"}],"name":"ChangedManagementProxy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"point","type":"uint32"},{"indexed":true,"name":"votingProxy","type":"address"}],"name":"ChangedVotingProxy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"primary","type":"string"},{"indexed":false,"name":"secondary","type":"string"},{"indexed":false,"name":"tertiary","type":"string"}],"name":"ChangedDns","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
+ etc/ecliptic.json view
@@ -0,0 +1,1 @@+[{"constant":true,"inputs":[{"name":"_interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_galaxy","type":"uint8"},{"name":"_proposal","type":"bytes32"}],"name":"startDocumentPoll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"detach","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"name":"approved","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_approved","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_proposal","type":"bytes32"}],"name":"updateDocumentPoll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"onUpgrade","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"InterfaceId_ERC165","outputs":[{"name":"","type":"bytes4"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_target","type":"address"},{"name":"_reset","type":"bool"}],"name":"transferPoint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_galaxy","type":"uint8"},{"name":"_target","type":"address"}],"name":"createGalaxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_transferProxy","type":"address"}],"name":"setTransferProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_encryptionKey","type":"bytes32"},{"name":"_authenticationKey","type":"bytes32"},{"name":"_cryptoSuiteVersion","type":"uint32"},{"name":"_discontinuous","type":"bool"}],"name":"configureKeys","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_sponsor","type":"uint32"}],"name":"canEscapeTo","outputs":[{"name":"canEscape","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"name":"doesExist","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_galaxy","type":"uint8"},{"name":"_proposal","type":"address"},{"name":"_vote","type":"bool"}],"name":"castUpgradeVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_proposal","type":"address"}],"name":"updateUpgradePoll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"owner","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_galaxy","type":"uint8"},{"name":"_proposal","type":"bytes32"},{"name":"_vote","type":"bool"}],"name":"castDocumentVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_manager","type":"address"}],"name":"setManagementProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_galaxy","type":"uint8"},{"name":"_proposal","type":"address"}],"name":"startUpgradePoll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_target","type":"address"}],"name":"spawn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_operator","type":"address"},{"name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_galaxy","type":"uint8"},{"name":"_voter","type":"address"}],"name":"setVotingProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_prefix","type":"uint16"},{"name":"_spawnProxy","type":"address"}],"name":"setSpawnProxy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_primary","type":"string"},{"name":"_secondary","type":"string"},{"name":"_tertiary","type":"string"}],"name":"setDnsDomains","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"reject","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"},{"name":"_sponsor","type":"uint32"}],"name":"escape","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"adopt","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_point","type":"uint32"}],"name":"cancelEscape","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"name":"_tokenURI","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"azimuth","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"claims","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"polls","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"name":"result","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"previousEcliptic","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_point","type":"uint32"},{"name":"_time","type":"uint256"}],"name":"getSpawnLimit","outputs":[{"name":"limit","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_previous","type":"address"},{"name":"_azimuth","type":"address"},{"name":"_polls","type":"address"},{"name":"_claims","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_approved","type":"address"},{"indexed":false,"name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_operator","type":"address"},{"indexed":false,"name":"_approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"to","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
+ lib/Network/Web3/Provider/Extended.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE LambdaCase #-}++module Network.Web3.Provider.Extended (+ Web3(..)+ , Web3Error(..)+ , runWeb3++ , Web3.Client.defaultSettings+ ) where++import qualified Control.Exception as Exception+import Control.Monad.Catch (MonadThrow)+import Control.Monad.Except (ExceptT, MonadError)+import qualified Control.Monad.Except as Except+import Control.Monad.IO.Class (MonadIO)+import qualified Control.Monad.State.Strict as State+import Control.Monad.State.Strict (MonadState, StateT)+import Network.Web3.Provider (Web3Error(..))+import Network.JsonRpc.TinyClient (JsonRpcClient)+import qualified Network.JsonRpc.TinyClient as Web3.Client++-- | A wrapper for the 'Ethereum.Provider.Web3' monad that provides a+-- 'MonadFail' instance.+newtype Web3 a = Web3 (ExceptT String (StateT JsonRpcClient IO) a)+ deriving newtype+ ( Functor+ , Applicative+ , Monad+ , MonadIO+ , MonadThrow+ , MonadError String+ , MonadState JsonRpcClient+ )++instance MonadFail Web3 where+ fail = Web3 . Except.liftEither . Left++instance Web3.Client.JsonRpc Web3++runWeb3 :: JsonRpcClient -> Web3 a -> IO a+runWeb3 client (Web3 action) =+ State.evalStateT (Except.runExceptT action) client >>= \case+ Left err -> Exception.throwIO (UserFail err)+ Right ok -> pure ok+
+ lib/Urbit/Azimuth.hs view
@@ -0,0 +1,20 @@++module Urbit.Azimuth (+ module E++ , Quantity+ , DefaultBlock(..)+ , blockNumber+ ) where++import Network.Ethereum.Api.Eth (blockNumber)+import Network.Ethereum.Api.Types (DefaultBlock(..), Quantity)+import Network.JsonRpc.TinyClient as E+import Network.Web3.Provider.Extended as E+import Urbit.Azimuth.Account as E+import Urbit.Azimuth.Azimuth as E+import Urbit.Azimuth.Contract as E+import Urbit.Azimuth.Ecliptic as E+import Urbit.Azimuth.Point as E+import Urbit.Azimuth.Transaction as E+
+ lib/Urbit/Azimuth/Account.hs view
@@ -0,0 +1,49 @@+module Urbit.Azimuth.Account (+ A.Account(..)+ , A.LocalKey(..)+ , A.LocalKeyAccount++ , C.PrivateKey+ , C.PublicKey+ , C.importKey+ , C.derivePubKey++ , K.DerivPath+ , K.DerivPathI(..)+ , K.ParsedPath(..)+ , K.parsePath++ , K.Mnemonic+ , K.Passphrase++ , toPrivateKey+ ) where++import qualified Crypto.Ethereum as C+import qualified Haskoin.Keys as K+import qualified Network.Ethereum.Account as A++-- | Recover a private key from a BIP39 mnemonic, passphrase, and HD derivation+-- path.+--+-- Note that you can use the monoid unit, 'mempty', to denote an empty or+-- absent passphrase.+--+-- >>> let mnem = "benefit crew supreme gesture quantum web media hazard theory mercy wing kitten"+-- >>> let hdpath = Deriv :| 44 :| 60 :| 0 :/ 0 :/ 0 -- m/44'/60'/0'/0/0+-- >>> toPrivateKey mnem mempty hdpath+toPrivateKey+ :: K.Mnemonic+ -> K.Passphrase+ -> K.DerivPath+ -> Either String A.LocalKey+toPrivateKey mnem pass path = do+ seed <- K.mnemonicToSeed pass mnem+ pure . flip A.LocalKey 1 -- NB this targets mainnet only+ . C.importKey+ . K.getSecKey+ . K.xPrvKey+ . K.derivePath path+ . K.makeXPrvKey+ $ seed+
+ lib/Urbit/Azimuth/Azimuth.hs view
@@ -0,0 +1,188 @@+{-# LANGUAGE ApplicativeDo #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ViewPatterns #-}++module Urbit.Azimuth.Azimuth (+ getPoint+ , getDetails+ , getRights+ , getSpawnCount+ , getSpawned+ , getSponsoringCount+ , getSponsoring+ , getOwnedPointCount+ , getOwnedPoints+ , getManagerForCount+ , getManagerFor+ , getVotingForCount+ , getVotingFor+ , getSpawningForCount+ , getSpawningFor+ , getTransferringForCount+ , getTransferringFor+ , getEscapeRequests+ , getEscapeRequestsCount+ ) where++import qualified Data.Default.Class as Default+import Network.JsonRpc.TinyClient (JsonRpc)+import Numeric.Natural+import qualified Urbit.Azimuth.Azimuth.Internal as I+import Urbit.Azimuth.Contract+import Urbit.Azimuth.Point+import qualified Urbit.Ob as Ob+import qualified Urbit.Ob.Extended as Ob++-- | Fetch a point's details and rights.+getPoint :: JsonRpc m => Ob.Patp -> Azimuth m Point+getPoint patp = do+ deets <- getDetails patp+ rights <- getRights patp+ pure (Point patp deets rights)++-- | Fetch a point's details.+getDetails :: JsonRpc m => Ob.Patp -> Azimuth m Details+getDetails patp = withContract azimuth $ do+ let point = Ob.patpToPoint patp++ ( CryptKey -> detailsCryptKey,+ AuthKey -> detailsAuthKey,+ detailsHasSponsor,+ detailsActive,+ detailsEscapeRequested,+ Ob.pointToPatp -> detailsSponsor,+ Ob.pointToPatp -> detailsEscapeRequestedTo,+ CryptoSuite -> detailsCryptoSuite,+ Life -> detailsLife,+ Rift -> detailsRift ) <- I.points point++ pure Details { .. }++-- | Fetch a point's rights.+getRights :: JsonRpc m => Ob.Patp -> Azimuth m Rights+getRights patp = withContract azimuth $ do+ let unzero x = if isZeroAddress x then Nothing else Just x+ point = Ob.patpToPoint patp++ ( rightsOwner,+ unzero -> rightsManagementProxy,+ unzero -> rightsSpawnProxy,+ unzero -> rightsVotingProxy,+ unzero -> rightsTransferProxy ) <- I.rights point++ pure Rights { .. }++-- | Get the number of points a point has spawned.+getSpawnCount :: JsonRpc m => Ob.Patp -> Azimuth m Natural+getSpawnCount patp = withContract azimuth $ do+ let point = Ob.patpToPoint patp+ count <- I.getSpawnCount point+ pure $ fromIntegral count++-- | Get a list of points that a point has spawned.+getSpawned :: JsonRpc m => Ob.Patp -> Azimuth m [Ob.Patp]+getSpawned patp = withContract azimuth $ do+ let point = Ob.patpToPoint patp+ children <- I.getSpawned point+ pure $ fmap Ob.pointToPatp children++-- | Get a list of points that a point is sponsoring.+getSponsoring :: JsonRpc m => Ob.Patp -> Azimuth m [Ob.Patp]+getSponsoring patp = withContract azimuth $ do+ let point = Ob.patpToPoint patp+ children <- I.getSponsoring point+ pure $ fmap Ob.pointToPatp children++-- | Get the number of points a point is sponsoring.+getSponsoringCount :: JsonRpc m => Ob.Patp -> Azimuth m Natural+getSponsoringCount patp = withContract azimuth $ do+ let point = Ob.patpToPoint patp+ count <- I.getSponsoringCount point+ pure $ fromIntegral count++-- | Get a list of points that are requesting escape from a point.+getEscapeRequests :: JsonRpc m => Ob.Patp -> Azimuth m [Ob.Patp]+getEscapeRequests patp = withContract azimuth $ do+ let point = Ob.patpToPoint patp+ children <- I.getEscapeRequests point+ pure $ fmap Ob.pointToPatp children++-- | Get the number of points that are requesting escape from a point.+getEscapeRequestsCount+ :: JsonRpc m+ => Ob.Patp+ -> Azimuth m Natural+getEscapeRequestsCount patp = withContract azimuth $ do+ let point = Ob.patpToPoint patp+ count <- I.getEscapeRequestsCount point+ pure $ fromIntegral count++-- | Get a list of points that an address owns.+getOwnedPoints :: JsonRpc m => Address -> Azimuth m [Ob.Patp]+getOwnedPoints addr = withContract azimuth $ do+ children <- I.getOwnedPoints addr+ pure $ fmap Ob.pointToPatp children++-- | Get the number of points that an address owns.+getOwnedPointCount :: JsonRpc m => Address -> Azimuth m Natural+getOwnedPointCount addr = withContract azimuth $ do+ count <- I.getOwnedPointCount addr+ pure $ fromIntegral count++-- | Get a list of points that an address manages.+getManagerFor :: JsonRpc m => Address -> Azimuth m [Ob.Patp]+getManagerFor addr = withContract azimuth $ do+ children <- I.getManagerFor addr+ pure $ fmap Ob.pointToPatp children++-- | Get the number of points that an address manages.+getManagerForCount :: JsonRpc m => Address -> Azimuth m Natural+getManagerForCount addr = withContract azimuth $ do+ count <- I.getManagerForCount addr+ pure $ fromIntegral count++-- | Get a list of points that an address can vote on behalf of.+getVotingFor :: JsonRpc m => Address -> Azimuth m [Ob.Patp]+getVotingFor addr = withContract azimuth $ do+ children <- I.getVotingFor addr+ pure $ fmap Ob.pointToPatp children++-- | Get the number of points that an address can vote on behalf of.+getVotingForCount :: JsonRpc m => Address -> Azimuth m Natural+getVotingForCount addr = withContract azimuth $ do+ count <- I.getVotingForCount addr+ pure $ fromIntegral count++-- | Get a list of points that an address is a spawn proxy for.+getSpawningFor :: JsonRpc m => Address -> Azimuth m [Ob.Patp]+getSpawningFor addr = withContract azimuth $ do+ children <- I.getSpawningFor addr+ pure $ fmap Ob.pointToPatp children++-- | Get the number of points that an address is a spawn proxy for.+getSpawningForCount :: JsonRpc m => Address -> Azimuth m Natural+getSpawningForCount addr = withContract azimuth $ do+ count <- I.getSpawningForCount addr+ pure $ fromIntegral count++-- | Get a list of points that an address is a transfer proxy for.+getTransferringFor+ :: JsonRpc m+ => Address+ -> Azimuth m [Ob.Patp]+getTransferringFor addr = withContract azimuth $ do+ children <- I.getTransferringFor addr+ pure $ fmap Ob.pointToPatp children++-- | Get the number of points that an address is a transfer proxy for.+getTransferringForCount+ :: JsonRpc m+ => Address+ -> Azimuth m Natural+getTransferringForCount addr = withContract azimuth $ do+ count <- I.getTransferringForCount addr+ pure $ fromIntegral count++isZeroAddress :: Address -> Bool+isZeroAddress addr = addr == Default.def+
+ lib/Urbit/Azimuth/Azimuth/Internal.hs view
@@ -0,0 +1,17 @@+{-# OPTIONS_GHC -fno-warn-missing-deriving-strategies #-}+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+{-# OPTIONS_GHC -fno-warn-missing-export-lists #-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}++module Urbit.Azimuth.Azimuth.Internal where++import qualified Network.Ethereum.Contract.TH as Ethereum.Contract++[Ethereum.Contract.abiFrom|etc/azimuth.json|]
+ lib/Urbit/Azimuth/Contract.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE NumericUnderscores #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module Urbit.Azimuth.Contract (+ Contracts(..)+ , getContracts+ , withContract++ , Azimuth(..)+ , runAzimuth+ ) where++import Control.Monad.Trans (lift)+import Control.Monad.Reader (ReaderT(..), ask)+import Data.Solidity.Prim.Address (Address)+import Network.Ethereum.Account (LocalKeyAccount, LocalKey, withAccount)+import qualified Network.Ethereum.Account as Ethereum.Account+import qualified Network.Ethereum.Account.Internal as AI+import qualified Network.Ethereum.Ens as Ethereum.Ens+import Network.JsonRpc.TinyClient (JsonRpc)++-- | Supported Azimuth contracts.+data Contracts = Contracts {+ azimuth :: Address+ , ecliptic :: Address+ } deriving stock Show++-- | The Azimuth type represents an authenticated connection to a JSON RPC by+-- way of a local private key, and has access to a 'Contracts' object.+newtype Azimuth m a =+ Azimuth (ReaderT Contracts (LocalKeyAccount m) a)+ deriving newtype (Functor, Applicative, Monad)++-- | Run an Azimuth action.+runAzimuth+ :: JsonRpc m+ => Contracts+ -> LocalKey+ -> Azimuth m a+ -> m a+runAzimuth contracts account (Azimuth action) = withAccount account $+ runReaderT action contracts++-- | Fetch the Azimuth and Ecliptic contracts by way of their ENS records.+getContracts :: JsonRpc m => m Contracts+getContracts = withAccount () $ do+ azimuth <- Ethereum.Ens.resolve "azimuth.eth"+ ecliptic <- Ethereum.Ens.resolve "ecliptic.eth"+ pure Contracts {..}++-- | Perform an Azimuth action, targeting the appropriate contract.+withContract+ :: Monad m+ => (Contracts -> Address)+ -> LocalKeyAccount m a+ -> Azimuth m a+withContract selector action = Azimuth $ do+ contracts <- ask+ lift $ Ethereum.Account.withParam (\param -> param {+ AI._to = Just (selector contracts)+ -- NB hardcoded to 40 gwei at present+ -- going to want a better way to specify gas price+ , AI._gasPrice = Just 40_000_000_000+ }) action+
+ lib/Urbit/Azimuth/Ecliptic.hs view
@@ -0,0 +1,295 @@+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE RecordWildCards #-}++module Urbit.Azimuth.Ecliptic (+ RevisionType(..)+ , Approval(..)+ , Reset(..)++ , exists+ , getApproved+ , isApprovedForAll+ , getSpawnLimit+ , canEscapeTo+ , configureKeys+ , createGalaxy+ , safeTransferFrom+ , transferFrom+ , approve+ , setApprovalForAll+ , setManagementProxy+ , spawn+ , setSpawnProxy+ , transferPoint+ , setTransferProxy+ , escape+ , cancelEscape+ , adopt+ , reject+ , detach+ , setVotingProxy+ , setDnsDomains+ ) where++import qualified Data.Text as T+import qualified Network.Ethereum.Api.Types as Api+import Network.JsonRpc.TinyClient (JsonRpc)+import Numeric.Natural+import Urbit.Azimuth.Contract+import qualified Urbit.Azimuth.Ecliptic.Internal as I+import Urbit.Azimuth.Point+import qualified Urbit.Ob as Ob+import qualified Urbit.Ob.Extended as Ob++-- | Key revision options.+data RevisionType =+ Rotate -- ^ Assign new keys+ | Breach -- ^ Assign new keys, breaching continuity in the process+ deriving stock (Eq, Show)++-- | Operator approval options.+data Approval =+ Approved -- ^ Operator is allowed to transfer ownership of all points+ | Disallowed -- ^ Operator is not allowed to transfer ownership of all points+ deriving stock (Eq, Show)++-- | Point transfer options.+data Reset =+ Preserve -- ^ Preserve existing key and permissions information+ | Clear -- ^ Reset (clear) existing key and permissions information+ deriving stock (Eq, Show)++-- | Check if a point is active.+exists :: JsonRpc m => Ob.Patp -> Azimuth m Bool+exists patp = withContract ecliptic $ do+ let point = Ob.patpToSolidity256 patp+ I.exists point++-- | Get the approved transfer proxy for a point.+getApproved :: JsonRpc m => Ob.Patp -> Azimuth m Address+getApproved patp = withContract ecliptic $ do+ let point = Ob.patpToSolidity256 patp+ I.getApproved point++-- | Check if an address is an operator for an owner.+isApprovedForAll+ :: JsonRpc m+ => Address+ -> Address+ -> Azimuth m Bool+isApprovedForAll owner operator = withContract ecliptic $+ I.isApprovedForAll owner operator++-- | Get the total number of children a point can spawn at some time.+getSpawnLimit+ :: JsonRpc m+ => Ob.Patp+ -> Natural+ -> Azimuth m Natural+getSpawnLimit patp time = withContract ecliptic $ do+ let point = Ob.patpToPoint patp+ limit <- I.getSpawnLimit point (fromIntegral time)+ pure $ fromIntegral limit++-- | Check if a point can escape to a sponsor.+canEscapeTo+ :: JsonRpc m+ => Ob.Patp+ -> Ob.Patp+ -> Azimuth m Bool+canEscapeTo point sponsor = withContract ecliptic $ do+ let pt = Ob.patpToPoint point+ sp = Ob.patpToPoint sponsor+ I.canEscapeTo pt sp++-- | Safely transfer a point between addresses (call recipient if it's a+-- contract).+safeTransferFrom+ :: JsonRpc m+ => Address+ -> Address+ -> Ob.Patp+ -> Azimuth m Api.TxReceipt+safeTransferFrom from to point = withContract ecliptic $ do+ let pt = Ob.patpToSolidity256 point+ I.safeTransferFrom from to pt++-- | Transfer a point between addresses (without notifying recipient contract).+transferFrom+ :: JsonRpc m+ => Address+ -> Address+ -> Ob.Patp+ -> Azimuth m Api.TxReceipt+transferFrom from to point = withContract ecliptic $ do+ let pt = Ob.patpToSolidity256 point+ I.transferFrom from to pt++-- | Approve an address to transfer ownership of a point.+approve+ :: JsonRpc m+ => Address+ -> Ob.Patp+ -> Azimuth m Api.TxReceipt+approve addr point = withContract ecliptic $ do+ let pt = Ob.patpToSolidity256 point+ I.approve addr pt++-- | Allow or disallow an operator to transfer ownership of all points owned by+-- the message sender.+setApprovalForAll+ :: JsonRpc m+ => Address+ -> Approval+ -> Azimuth m Api.TxReceipt+setApprovalForAll addr approval = withContract ecliptic $+ I.setApprovalForAll addr (approval == Approved)++-- | Configure the management address for a point owned by the message sender.+setManagementProxy+ :: JsonRpc m+ => Ob.Patp+ -> Address+ -> Azimuth m Api.TxReceipt+setManagementProxy patp addr = withContract ecliptic $ do+ let pt = Ob.patpToPoint patp+ I.setManagementProxy pt addr++-- | Configure a point's keys, optionally incrementing the continuity number.+configureKeys+ :: JsonRpc m+ => Ob.Patp+ -> Keys+ -> RevisionType+ -> Azimuth m Api.TxReceipt+configureKeys patp Keys {..} breach = do+ let point = Ob.patpToPoint patp+ ck = fromCryptKey keyCrypt+ ak = fromAuthKey keyAuth+ cs = fromCryptoSuite keyCryptoSuite+ bc = breach == Breach++ withContract ecliptic $ I.configureKeys point ck ak cs bc++-- | Spawn a point, giving ownership of it to the target address.+spawn+ :: JsonRpc m+ => Ob.Patp+ -> Address+ -> Azimuth m Api.TxReceipt+spawn point addr = withContract ecliptic $ do+ let pt = Ob.patpToPoint point+ I.spawn pt addr++-- | Give an address the right to spawn points with the given prefix.+setSpawnProxy+ :: JsonRpc m+ => Ob.Patp+ -> Address+ -> Azimuth m Api.TxReceipt+setSpawnProxy patp addr = case Ob.patpToSolidity16 patp of+ -- NB a proper way to handle this sort of error would be nice+ Left _ -> error (show patp <> " is not a star or galaxy")+ Right pt -> withContract ecliptic $ I.setSpawnProxy pt addr++-- | Transfer a point between addresses (without notifying recipient contract).+transferPoint+ :: JsonRpc m+ => Ob.Patp+ -> Address+ -> Reset+ -> Azimuth m Api.TxReceipt+transferPoint point addr reset = withContract ecliptic $ do+ let pt = Ob.patpToPoint point+ I.transferPoint pt addr (reset == Clear)++-- | Configure the transfer proxy address for a point owned by the message+-- sender.+setTransferProxy+ :: JsonRpc m+ => Ob.Patp+ -> Address+ -> Azimuth m Api.TxReceipt+setTransferProxy patp addr = withContract ecliptic $ do+ let pt = Ob.patpToPoint patp+ I.setTransferProxy pt addr++-- | Request escape from 'point' to 'sponsor'.+escape+ :: JsonRpc m+ => Ob.Patp+ -> Ob.Patp+ -> Azimuth m Api.TxReceipt+escape point sponsor = withContract ecliptic $ do+ let pt = Ob.patpToPoint point+ sp = Ob.patpToPoint sponsor+ I.escape pt sp++-- | Cancel a point's escape request.+cancelEscape+ :: JsonRpc m+ => Ob.Patp+ -> Azimuth m Api.TxReceipt+cancelEscape point = withContract ecliptic $ do+ let pt = Ob.patpToPoint point+ I.cancelEscape pt++-- | As a sponsor, accept a point's escape request.+adopt+ :: JsonRpc m+ => Ob.Patp+ -> Azimuth m Api.TxReceipt+adopt escapee = withContract ecliptic $ do+ let pt = Ob.patpToPoint escapee+ I.adopt pt++-- | As a sponsor, reject a point's escape request.+reject+ :: JsonRpc m+ => Ob.Patp+ -> Azimuth m Api.TxReceipt+reject escapee = withContract ecliptic $ do+ let pt = Ob.patpToPoint escapee+ I.reject pt++-- | As a sponsor, stop sponsoring a point.+detach+ :: JsonRpc m+ => Ob.Patp+ -> Azimuth m Api.TxReceipt+detach escapee = withContract ecliptic $ do+ let pt = Ob.patpToPoint escapee+ I.detach pt++-- | Configure the voting proxy address for a point owned by the message+-- sender.+setVotingProxy+ :: JsonRpc m+ => Ob.Patp+ -> Address+ -> Azimuth m Api.TxReceipt+setVotingProxy patp addr = case Ob.patpToGalaxy patp of+ -- NB a proper way to handle this sort of error would be nice+ Left _ -> error (show patp <> " is not a galaxy")+ Right gal -> withContract ecliptic $ I.setVotingProxy gal addr++-- | Set primary, secondary, and tertiary DNS domains for the ecliptic.+setDnsDomains+ :: JsonRpc m+ => T.Text+ -> T.Text+ -> T.Text+ -> Azimuth m Api.TxReceipt+setDnsDomains prim seco tert = withContract ecliptic $+ I.setDnsDomains prim seco tert++-- | Create the specified galaxy.+createGalaxy+ :: JsonRpc m+ => Ob.Patp+ -> Address+ -> Azimuth m Api.TxReceipt+createGalaxy patp addr = case Ob.patpToGalaxy patp of+ -- NB a proper way to handle this sort of error would be nice+ Left _ -> error (show patp <> " is not a galaxy")+ Right gal -> withContract ecliptic $ I.createGalaxy gal addr
+ lib/Urbit/Azimuth/Ecliptic/Internal.hs view
@@ -0,0 +1,17 @@+{-# OPTIONS_GHC -fno-warn-missing-deriving-strategies #-}+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+{-# OPTIONS_GHC -fno-warn-missing-export-lists #-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE QuasiQuotes #-}++module Urbit.Azimuth.Ecliptic.Internal where++import qualified Network.Ethereum.Contract.TH as Ethereum.Contract++[Ethereum.Contract.abiFrom|etc/ecliptic.json|]
+ lib/Urbit/Azimuth/Point.hs view
@@ -0,0 +1,228 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE RecordWildCards #-}++module Urbit.Azimuth.Point (+ Point(..)+ , Details(..)+ , Rights(..)++ , Keys(..)+ , CryptKey(..)+ , AuthKey(..)+ , CryptoSuite(..)+ , keyInformation++ , Life(..)+ , Rift(..)++ , Address++ , isOwner+ , isLive+ , isSponsor+ , isRequestingEscapeTo+ , isSpawnProxy+ , isTransferProxy+ , isManagementProxy+ , isVotingProxy++ , hasBeenLinked+ , canManageNetworkKeys+ , canSponsor+ , canManage+ , canSpawn+ , canVote+ , canTransfer+ ) where++import qualified Data.ByteArray.Sized as DBS+import Data.Solidity.Prim.Address (Address)+import qualified Data.Solidity.Prim as Solidity.Prim (UIntN, BytesN)+import GHC.Generics (Generic)+import Prelude+import Urbit.Ob (Patp)+import qualified Urbit.Ob as Ob++-- | An Azimuth point, represented by its \@p, 'Details', and 'Rights'.+data Point = Point {+ pointPatp :: Patp+ , pointDetails :: Details+ , pointRights :: Rights+ }+ deriving stock (Show, Eq, Generic)++-- | Various information about a 'Point'.+data Details = Details {+ detailsCryptKey :: CryptKey+ , detailsAuthKey :: AuthKey+ , detailsHasSponsor :: Bool+ , detailsActive :: Bool+ , detailsEscapeRequested :: Bool+ , detailsSponsor :: Patp+ , detailsEscapeRequestedTo :: Patp+ , detailsCryptoSuite :: CryptoSuite+ , detailsLife :: Life+ , detailsRift :: Rift+ }+ deriving stock (Show, Eq, Generic)++-- | Ownership and proxy information for a 'Point'.+data Rights = Rights {+ rightsOwner :: Address+ , rightsManagementProxy :: Maybe Address+ , rightsSpawnProxy :: Maybe Address+ , rightsVotingProxy :: Maybe Address+ , rightsTransferProxy :: Maybe Address+ }+ deriving stock (Show, Eq, Generic)++-- | Grab a point's key information.+keyInformation :: Point -> Keys+keyInformation Point {..} = Keys {+ keyCrypt = detailsCryptKey+ , keyAuth = detailsAuthKey+ , keyCryptoSuite = detailsCryptoSuite+ }+ where+ Details {..} = pointDetails+-- | A point's public encryption key.+newtype CryptKey = CryptKey {+ fromCryptKey :: Solidity.Prim.BytesN 32+ }+ deriving stock (Show, Eq)+ deriving newtype (Semigroup, Monoid)++-- | A point's public authentication key.+newtype AuthKey = AuthKey {+ fromAuthKey :: Solidity.Prim.BytesN 32+ }+ deriving stock (Show, Eq)+ deriving newtype (Semigroup, Monoid)++-- | A point's crypto suite version.+newtype CryptoSuite = CryptoSuite {+ fromCryptoSuite :: Solidity.Prim.UIntN 32+ }+ deriving stock (Show, Eq, Ord)+ deriving newtype (Num, Real, Enum, Bounded, Integral)++-- | A point's life (i.e., recorded number of key revisions).+newtype Life = Life {+ fromLife :: Solidity.Prim.UIntN 32+ }+ deriving stock (Show, Eq, Ord)+ deriving newtype (Num, Real, Enum, Bounded, Integral)++-- | A point's rift (i.e., recorded number of continuity breaches).+newtype Rift = Rift {+ fromRift :: Solidity.Prim.UIntN 32+ }+ deriving stock (Show, Eq, Ord)+ deriving newtype (Num, Real, Enum, Bounded, Integral)++-- | Public key information for a 'Point'.+data Keys = Keys {+ keyCrypt :: CryptKey+ , keyAuth :: AuthKey+ , keyCryptoSuite :: CryptoSuite+ } deriving stock (Show, Eq)++-- | Check if an address is the owner of a point.+isOwner :: Point -> Address -> Bool+isOwner Point {..} addr = rightsOwner pointRights == addr++-- | Check if a point has been booted.+hasBeenLinked :: Point -> Bool+hasBeenLinked = (> 0) . detailsLife . pointDetails++-- | Check if a point is live.+isLive :: Point -> Bool+isLive Point {..} =+ fromCryptKey detailsCryptKey /= DBS.zero+ && fromAuthKey detailsAuthKey /= DBS.zero+ && fromCryptoSuite detailsCryptoSuite /= 0+ where+ Details {..} = pointDetails++-- | Check if a point is the sponsor of another.+isSponsor :: Point -> Patp -> Bool+isSponsor Point {..} point =+ detailsHasSponsor && detailsSponsor == point+ where+ Details {..} = pointDetails++-- | Check if a point is requesting escape to another point.+isRequestingEscapeTo :: Point -> Patp -> Bool+isRequestingEscapeTo Point {..} patp =+ detailsEscapeRequested && detailsEscapeRequestedTo == patp+ where+ Details {..} = pointDetails++-- | Check if an address is a spawn proxy for a point.+isSpawnProxy :: Point -> Address -> Bool+isSpawnProxy Point {..} addr = case rightsSpawnProxy pointRights of+ Just a -> a == addr+ Nothing -> False++-- | Check if an address is a transfer proxy for a point.+isTransferProxy :: Point -> Address -> Bool+isTransferProxy Point {..} addr = case rightsTransferProxy pointRights of+ Just a -> a == addr+ Nothing -> False++-- | Check if an address is a management proxy for a point.+isManagementProxy :: Point -> Address -> Bool+isManagementProxy Point {..} addr = case rightsManagementProxy pointRights of+ Just a -> a == addr+ Nothing -> False++-- | Check if an address is a voting proxy for a point.+isVotingProxy :: Point -> Address -> Bool+isVotingProxy Point {..} addr = case rightsVotingProxy pointRights of+ Just a -> a == addr+ Nothing -> False++-- | Check if an address can manage a point's networking keys.+canManageNetworkKeys :: Point -> Address -> Bool+canManageNetworkKeys point addr =+ canManage point addr+ && hasBeenLinked point++-- | Check if a point can sponsor another.+canSponsor :: Point -> Bool+canSponsor Point {..} = case Ob.clan pointPatp of+ Ob.Galaxy -> True+ Ob.Star -> True+ _ -> False++-- | Check if an address can manage a point.+canManage :: Point -> Address -> Bool+canManage point addr =+ isOwner point addr+ || isManagementProxy point addr++-- | Check if an address can spawn for a point.+canSpawn :: Point -> Address -> Bool+canSpawn point addr =+ canSponsor point+ && hasBeenLinked point+ && (isOwner point addr || isSpawnProxy point addr)++-- | Check if an address can vote for a point.+canVote :: Point -> Address -> Bool+canVote point@Point {..} addr =+ Ob.Galaxy == Ob.clan pointPatp+ && detailsActive+ && (isOwner point addr || isVotingProxy point addr)+ where+ Details {..} = pointDetails++-- | Check if an address can transfer ownership of a point.+canTransfer :: Point -> Address -> Bool+canTransfer point addr =+ isOwner point addr+ || isTransferProxy point addr+
+ lib/Urbit/Azimuth/Transaction.hs view
@@ -0,0 +1,7 @@++module Urbit.Azimuth.Transaction (+ Api.TxReceipt(..)+ ) where++import qualified Network.Ethereum.Api.Types as Api+
+ lib/Urbit/Ob/Extended.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE DataKinds #-}++module Urbit.Ob.Extended (+ patpToPoint+ , patpToSolidity16+ , patpToSolidity256+ , patpToGalaxy+ , pointToPatp+ ) where++import qualified Data.Solidity.Prim+import qualified Urbit.Ob as Ob++data ObError = InvalidClass Ob.Class++-- | Convert a @p value to an Azimuth point.+--+-- Note that moon, comet, and higher-byte @p values will silently overflow on+-- conversion to a 32-bit Azimuth point!+patpToPoint :: Ob.Patp -> Data.Solidity.Prim.UIntN 32+patpToPoint = fromIntegral . Ob.fromPatp++-- | Convert a @p value to a 256-bit integer.+patpToSolidity256 :: Ob.Patp -> Data.Solidity.Prim.UIntN 256+patpToSolidity256 = fromIntegral . Ob.fromPatp++-- | Convert a star-or-galaxy class @p value to a 16-bit integer.+patpToSolidity16 :: Ob.Patp -> Either ObError (Data.Solidity.Prim.UIntN 16)+patpToSolidity16 patp = case clan of+ Ob.Galaxy -> pure (fromIntegral (Ob.fromPatp patp))+ Ob.Star -> pure (fromIntegral (Ob.fromPatp patp))+ _ -> Left (InvalidClass clan)+ where+ clan = Ob.clan patp++-- | Convert a galaxy-class @p value to an Azimuth point.+patpToGalaxy :: Ob.Patp -> Either ObError (Data.Solidity.Prim.UIntN 8)+patpToGalaxy patp = case clan of+ Ob.Galaxy -> pure (fromIntegral (Ob.fromPatp patp))+ _ -> Left (InvalidClass clan)+ where+ clan = Ob.clan patp++-- | Convert an Azimuth point to a @p value.+pointToPatp :: Data.Solidity.Prim.UIntN 32 -> Ob.Patp+pointToPatp = Ob.patp . fromIntegral+
+ test/Doc.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE OverloadedStrings #-}++import qualified Urbit.Azimuth as A+import qualified Urbit.Ob as Ob++-- A simple test endpoint. You'll probably want to set up your own.+infura :: String+infura = "https://mainnet.infura.io/v3/b7d2af9f01534031ba773374f766ef65"++-- A simple example of setting up an endpoint, fetching the Azimuth contracts,+-- getting a private key from a BIP39 mnemonic and HD path, and fetching ~zod's+-- public information.++main :: IO ()+main = do+ endpoint <- A.defaultSettings infura+ contracts <- A.runWeb3 endpoint A.getContracts++ -- use a test mnemonic+ let mnem = "benefit crew supreme gesture quantum "+ <> "web media hazard theory mercy wing kitten"++ -- and a standard HD path (m/44'/60'/0'/0/0)+ let hdpath = A.Deriv A.:| 44 A.:| 60 A.:| 0 A.:/ 0 A.:/ 0++ -- unlock the corresponding account+ let account = case A.toPrivateKey mnem mempty hdpath of+ Left _ -> error "bogus creds"+ Right acc -> acc++ let zod = Ob.patp 0++ -- fetch ~zod's public info+ point <- A.runWeb3 endpoint $+ A.runAzimuth contracts account $+ A.getPoint zod++ -- print it+ print point
+ test/Main.hs view
@@ -0,0 +1,167 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}++module Main where++import Control.Exception (bracket)+import qualified Data.Text as T+import qualified Shelly as S+import Test.Hspec+import qualified Urbit.Azimuth as A+import qualified Urbit.Ob as Ob++ginit :: IO T.Text+ginit = S.shelly $ S.verbosely $ do+ pod <- S.run "docker" [+ "run"+ , "-d"+ , "-p", "8545:8545"+ , "trufflesuite/ganache-cli:latest"+ , "--networkId", "1"+ , "-m", "'benefit crew supreme gesture quantum web media hazard " <>+ "theory mercy wing kitten'"+ ]++ -- give it a sec to get going+ _ <- S.run_ "sleep" [ "5" ]++ pure (T.takeWhile (/= '\n') pod)++gkill :: T.Text -> IO ()+gkill pod = S.shelly $ S.verbosely $+ S.run_ "docker" [+ "stop"+ , pod+ ]++-- FIXME need to add a contract deployment action here+withGanache :: IO () -> IO ()+withGanache action = bracket ginit gkill (const action)++data Config = Config {+ endpt :: String+ , mnem :: A.Mnemonic+ , pbase :: A.DerivPath+ , pk0 :: A.LocalKey+ , pk1 :: A.LocalKey+ , pk2 :: A.LocalKey+ , contracts :: A.Contracts+ }++testConfig :: Config+testConfig = Config {..} where+ endpt = "http://localhost:8545"+ pbase = A.Deriv A.:| 44 A.:| 60 A.:| 0 A.:/ 0+ Right pk0 = A.toPrivateKey mnem mempty (pbase A.:/ 0)+ Right pk1 = A.toPrivateKey mnem mempty (pbase A.:/ 1)+ Right pk2 = A.toPrivateKey mnem mempty (pbase A.:/ 2)++ mnem = "benefit crew supreme gesture quantum web media hazard " <>+ "theory mercy wing kitten"++ contracts = A.Contracts {+ azimuth = "0x863d9c2e5c4c133596cfac29d55255f0d0f86381"+ , ecliptic = "0x56db68f29203ff44a803faa2404a44ecbb7a7480"+ }++main :: IO ()+main = do+ let Config {..} = testConfig+ zod = Ob.patp 0+ nec = Ob.patp 1+ bud = Ob.patp 2+ wes = Ob.patp 3+ nidsut = Ob.patp 15663360++ bytes = "0x7768617465766572000000000000000000000000000000000000000000000000"++ keys = A.Keys {+ keyCrypt = A.CryptKey bytes+ , keyAuth = A.AuthKey bytes+ , keyCryptoSuite = A.CryptoSuite 1+ }++ endpoint <- A.defaultSettings endpt++ -- NB eventually this should use the 'around_ withGanache' context, but a+ -- contract deployment action will need to be added first.+ --+ -- until then, you should run these tests by booting a ganache node in+ -- the background and deploying the contracts with truffle. you may+ -- want to use the 'test:setup' and 'test:cleanup' npm actions in+ -- azimuth-js.++ hspec $ do+ it "creates galaxies properly" $ do+ (z0, n0) <- A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $ do+ zp <- A.getPoint zod+ np <- A.getPoint nec+ pure (zp, np)++ A.pointDetails z0 `shouldNotSatisfy` A.detailsActive+ A.pointDetails n0 `shouldNotSatisfy` A.detailsActive++ A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $+ A.createGalaxy zod "0x6DEfFb0caFDB11D175F123F6891AA64F01c24F7d"++ A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $+ A.createGalaxy nec "0x6DEfFb0caFDB11D175F123F6891AA64F01c24F7d"++ (z1, n1) <- A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $ do+ zp <- A.getPoint zod+ np <- A.getPoint nec+ pure (zp, np)++ A.pointDetails z1 `shouldSatisfy` A.detailsActive+ A.pointDetails n1 `shouldSatisfy` A.detailsActive++ it "rotates keys properly" $ do+ A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $+ A.configureKeys zod keys A.Rotate++ A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $+ A.configureKeys nec keys A.Rotate++ (kz, kn) <- A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $ do+ zp <- A.getPoint zod+ np <- A.getPoint nec+ pure (A.keyInformation zp, A.keyInformation np)++ A.keyCrypt kz `shouldBe` (A.CryptKey bytes)+ A.keyAuth kz `shouldBe` (A.AuthKey bytes)+ A.keyCrypt kn `shouldBe` (A.CryptKey bytes)+ A.keyAuth kn `shouldBe` (A.AuthKey bytes)++ it "breaches continuity properly" $ do+ (z0, n0) <- A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $ do+ zp <- A.getPoint zod+ np <- A.getPoint nec+ pure (zp, np)++ A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $+ A.configureKeys zod keys A.Breach++ A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $+ A.configureKeys nec keys A.Breach++ (z1, n1) <- A.runWeb3 endpoint $+ A.runAzimuth contracts pk0 $ do+ zp <- A.getPoint zod+ np <- A.getPoint nec+ pure (zp, np)++ let getRift = A.detailsRift . A.pointDetails++ getRift z1 `shouldSatisfy` (> (getRift z0))+ getRift n1 `shouldSatisfy` (> (getRift n0))+