flow_client 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/console CHANGED
File without changes
data/bin/setup CHANGED
File without changes
@@ -0,0 +1,12 @@
1
+ version: "3"
2
+ services:
3
+ emulator:
4
+ image: gcr.io/flow-container-registry/emulator:latest
5
+ ports:
6
+ - "8080:8080"
7
+ - "3569:3569"
8
+ environment:
9
+ - FLOW_SERVICEPRIVATEKEY=4d9287571c8bff7482ffc27ef68d5b4990f9bd009a1e9fa812aae08ba167d57f
10
+ - FLOW_SERVICEKEYSIGALGO=ECDSA_P256
11
+ - FLOW_SERVICEKEYHASHALGO=SHA3_256
12
+ - FLOW_VERBOSE=true
data/flow.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "emulators": {
3
+ "default": {
4
+ "port": 3569,
5
+ "serviceAccount": "emulator-account"
6
+ }
7
+ },
8
+ "contracts": {},
9
+ "networks": {
10
+ "emulator": "127.0.0.1:3569",
11
+ "mainnet": "access.mainnet.nodes.onflow.org:9000",
12
+ "testnet": "access.devnet.nodes.onflow.org:9000"
13
+ },
14
+ "accounts": {
15
+ "emulator-account": {
16
+ "address": "f8d6e0586b0a20c7",
17
+ "key": "38a7eef2053e165c2d635fb471fb26c91d9da2914a8f13c58ec210412adb2067"
18
+ }
19
+ },
20
+ "deployments": {}
21
+ }
@@ -0,0 +1,144 @@
1
+ /**
2
+
3
+ ## The Flow Non-Fungible Token standard
4
+
5
+ ## `NonFungibleToken` contract interface
6
+
7
+ The interface that all non-fungible token contracts could conform to.
8
+ If a user wants to deploy a new nft contract, their contract would need
9
+ to implement the NonFungibleToken interface.
10
+
11
+ Their contract would have to follow all the rules and naming
12
+ that the interface specifies.
13
+
14
+ ## `NFT` resource
15
+
16
+ The core resource type that represents an NFT in the smart contract.
17
+
18
+ ## `Collection` Resource
19
+
20
+ The resource that stores a user's NFT collection.
21
+ It includes a few functions to allow the owner to easily
22
+ move tokens in and out of the collection.
23
+
24
+ ## `Provider` and `Receiver` resource interfaces
25
+
26
+ These interfaces declare functions with some pre and post conditions
27
+ that require the Collection to follow certain naming and behavior standards.
28
+
29
+ They are separate because it gives the user the ability to share a reference
30
+ to their Collection that only exposes the fields and functions in one or more
31
+ of the interfaces. It also gives users the ability to make custom resources
32
+ that implement these interfaces to do various things with the tokens.
33
+
34
+ By using resources and interfaces, users of NFT smart contracts can send
35
+ and receive tokens peer-to-peer, without having to interact with a central ledger
36
+ smart contract.
37
+
38
+ To send an NFT to another user, a user would simply withdraw the NFT
39
+ from their Collection, then call the deposit function on another user's
40
+ Collection to complete the transfer.
41
+
42
+ */
43
+
44
+ // The main NFT contract interface. Other NFT contracts will
45
+ // import and implement this interface
46
+ //
47
+ pub contract interface NonFungibleToken {
48
+
49
+ // The total number of tokens of this type in existence
50
+ pub var totalSupply: UInt64
51
+
52
+ // Event that emitted when the NFT contract is initialized
53
+ //
54
+ pub event ContractInitialized()
55
+
56
+ // Event that is emitted when a token is withdrawn,
57
+ // indicating the owner of the collection that it was withdrawn from.
58
+ //
59
+ // If the collection is not in an account's storage, `from` will be `nil`.
60
+ //
61
+ pub event Withdraw(id: UInt64, from: Address?)
62
+
63
+ // Event that emitted when a token is deposited to a collection.
64
+ //
65
+ // It indicates the owner of the collection that it was deposited to.
66
+ //
67
+ pub event Deposit(id: UInt64, to: Address?)
68
+
69
+ // Interface that the NFTs have to conform to
70
+ //
71
+ pub resource interface INFT {
72
+ // The unique ID that each NFT has
73
+ pub let id: UInt64
74
+ }
75
+
76
+ // Requirement that all conforming NFT smart contracts have
77
+ // to define a resource called NFT that conforms to INFT
78
+ pub resource NFT: INFT {
79
+ pub let id: UInt64
80
+ }
81
+
82
+ // Interface to mediate withdraws from the Collection
83
+ //
84
+ pub resource interface Provider {
85
+ // withdraw removes an NFT from the collection and moves it to the caller
86
+ pub fun withdraw(withdrawID: UInt64): @NFT {
87
+ post {
88
+ result.id == withdrawID: "The ID of the withdrawn token must be the same as the requested ID"
89
+ }
90
+ }
91
+ }
92
+
93
+ // Interface to mediate deposits to the Collection
94
+ //
95
+ pub resource interface Receiver {
96
+
97
+ // deposit takes an NFT as an argument and adds it to the Collection
98
+ //
99
+ pub fun deposit(token: @NFT)
100
+ }
101
+
102
+ // Interface that an account would commonly
103
+ // publish for their collection
104
+ pub resource interface CollectionPublic {
105
+ pub fun deposit(token: @NFT)
106
+ pub fun getIDs(): [UInt64]
107
+ pub fun borrowNFT(id: UInt64): &NFT
108
+ }
109
+
110
+ // Requirement for the the concrete resource type
111
+ // to be declared in the implementing contract
112
+ //
113
+ pub resource Collection: Provider, Receiver, CollectionPublic {
114
+
115
+ // Dictionary to hold the NFTs in the Collection
116
+ pub var ownedNFTs: @{UInt64: NFT}
117
+
118
+ // withdraw removes an NFT from the collection and moves it to the caller
119
+ pub fun withdraw(withdrawID: UInt64): @NFT
120
+
121
+ // deposit takes a NFT and adds it to the collections dictionary
122
+ // and adds the ID to the id array
123
+ pub fun deposit(token: @NFT)
124
+
125
+ // getIDs returns an array of the IDs that are in the collection
126
+ pub fun getIDs(): [UInt64]
127
+
128
+ // Returns a borrowed reference to an NFT in the collection
129
+ // so that the caller can read data and call methods from it
130
+ pub fun borrowNFT(id: UInt64): &NFT {
131
+ pre {
132
+ self.ownedNFTs[id] != nil: "NFT does not exist in the collection!"
133
+ }
134
+ }
135
+ }
136
+
137
+ // createEmptyCollection creates an empty Collection
138
+ // and returns it to the caller so that they can own NFTs
139
+ pub fun createEmptyCollection(): @Collection {
140
+ post {
141
+ result.getIDs().length == 0: "The created collection must be empty!"
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,16 @@
1
+ transaction(publicKey: String, weight: UFix64) {
2
+ prepare(signer: AuthAccount) {
3
+ // signer.addPublicKey(publicKey.decodeHex())
4
+
5
+ let key = PublicKey(
6
+ publicKey: publicKey.decodeHex(),
7
+ signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
8
+ )
9
+
10
+ signer.keys.add(
11
+ publicKey: key,
12
+ hashAlgorithm: HashAlgorithm.SHA3_256,
13
+ weight: weight
14
+ )
15
+ }
16
+ }
@@ -0,0 +1,5 @@
1
+ transaction(name: String, code: String) {
2
+ prepare(signer: AuthAccount) {
3
+ signer.contracts.add(name: name, code: code.decodeHex())
4
+ }
5
+ }
@@ -0,0 +1,21 @@
1
+ transaction(publicKeys: [String], contracts: {String: String}) {
2
+ prepare(signer: AuthAccount) {
3
+ let acct = AuthAccount(payer: signer)
4
+ for keyHex in publicKeys {
5
+ let key = PublicKey(
6
+ publicKey: keyHex.decodeHex(),
7
+ signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
8
+ )
9
+
10
+ acct.keys.add(
11
+ publicKey: key,
12
+ hashAlgorithm: HashAlgorithm.SHA3_256,
13
+ weight: 1000.0
14
+ )
15
+ }
16
+
17
+ for contract in contracts.keys {
18
+ acct.contracts.add(name: contract, code: contracts[contract]!.decodeHex())
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,5 @@
1
+ transaction(name: String) {
2
+ prepare(signer: AuthAccount) {
3
+ signer.contracts.remove(name: name)
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ transaction(name: String, code: String) {
2
+ prepare(signer: AuthAccount) {
3
+ signer.contracts.update__experimental(name: name, code: code.decodeHex())
4
+ }
5
+ }
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlowClient
4
+ class AccountKey
5
+ attr_accessor :public_key,
6
+ :index, :sequence_number,
7
+ :sign_algo, :hash_algo,
8
+ :weight, :revoked
9
+
10
+ def initialize(public_key: nil, index: nil, sequence_number: nil, weight: 1000, revoked: false, hash_algo: FlowClient::Crypto::HashAlgos::SHA3_256)
11
+ @public_key = public_key
12
+ @index = index
13
+ @sequence_number = sequence_number
14
+ @weight = weight
15
+ @revoked = revoked
16
+ @hash_algo = hash_algo
17
+ end
18
+ end
19
+
20
+ class Account
21
+ attr_accessor :address, :balance, :keys, :contracts
22
+
23
+ def initialize(address: nil, balance: nil, keys: [], contracts: {})
24
+ @keys = keys
25
+ @address = address
26
+ @balance = balance
27
+ @contracts = {}
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,75 @@
1
+ module FlowClient
2
+
3
+ # Represents a block
4
+ class Block
5
+ attr_accessor :id,
6
+ :parent_id,
7
+ :height,
8
+ :timestamp,
9
+ :collection_guarantees,
10
+ :block_seals,
11
+ :signatures
12
+
13
+ def initialize
14
+ @id = nil
15
+ @parent_id = nil
16
+ @height = nil
17
+ @timestamp = nil
18
+ @collection_guarantees = []
19
+ @block_seals = []
20
+ @signatures = []
21
+ end
22
+
23
+ def self.parse_grpc_block_response(block_response)
24
+ block = Block.new
25
+ block.id = block_response.block.id.unpack1("H*")
26
+ block.parent_id = block_response.block.parent_id.unpack1("H*")
27
+ block.height = block_response.block.height
28
+ block.timestamp = FlowClient::Utils.parse_protobuf_timestamp(block_response.block.timestamp)
29
+ block.collection_guarantees = block_response.block.collection_guarantees.to_a.map { |cg| FlowClient::CollectionGuarantee.parse_grpc_type(cg) }
30
+ block.block_seals = block_response.block.block_seals.to_a.map { |seal| FlowClient::BlockSeal.parse_grpc_type(seal) }
31
+ block.signatures = block_response.block.signatures.to_a.map { |sig| sig.unpack1("H*") }
32
+ block
33
+ end
34
+ end
35
+
36
+ # Represents a block seal
37
+ class BlockSeal
38
+ attr_accessor :block_id,
39
+ :execution_receipt_id,
40
+ :execution_receipt_signatures,
41
+ :result_approval_signatures
42
+
43
+ def initialize
44
+ @block_id = nil
45
+ @execution_receipt_id = nil
46
+ @execution_receipt_signatures = []
47
+ @result_approval_signatures = []
48
+ end
49
+
50
+ def self.parse_grpc_type(grpc_type)
51
+ block_seal = BlockSeal.new
52
+ block_seal.block_id = grpc_type.block_id.unpack1("H*")
53
+ block_seal.execution_receipt_id = grpc_type.execution_receipt_id.unpack1("H*")
54
+ block_seal.execution_receipt_signatures = grpc_type.execution_receipt_signatures.to_a.map { |sig| sig.unpack1("H*") }
55
+ block_seal.result_approval_signatures = grpc_type.result_approval_signatures.to_a.map { |sig| sig.unpack1("H*") }
56
+ block_seal
57
+ end
58
+ end
59
+
60
+ # Represents a block header
61
+ class BlockHeader
62
+ attr_accessor :id, :parent_id, :height, :timestamp
63
+
64
+ def initialize
65
+ end
66
+
67
+ def self.parse_grpc_type(grpc_type)
68
+ header = BlockHeader.new
69
+ header.id = grpc_type.id.unpack1("H*")
70
+ header.height = grpc_type.height
71
+ header.timestamp = FlowClient::Utils.parse_protobuf_timestamp(grpc_type.timestamp)
72
+ header
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,197 @@
1
+ require "ostruct"
2
+
3
+ module FlowClient
4
+ module CadenceType
5
+ # class CadenceType
6
+ # def to_json
7
+ # end
8
+ # end
9
+
10
+ # class String
11
+ # end
12
+
13
+ def self.String(value)
14
+ OpenStruct.new(type: "String", value: value.to_s)
15
+ end
16
+
17
+ def self.Optional(value = nil)
18
+ OpenStruct.new(type: "Optional", value: value)
19
+ end
20
+
21
+ def self.Void()
22
+ OpenStruct.new(type: "Void")
23
+ end
24
+
25
+ def self.Bool(bool)
26
+ OpenStruct.new(type: "Bool", value: bool.to_s.downcase == "true")
27
+ end
28
+
29
+ def self.Address(address)
30
+ OpenStruct.new(type: "Address", value: address.to_s)
31
+ end
32
+
33
+ def self.Int(value)
34
+ OpenStruct.new(type: "Int", value: value.to_s)
35
+ end
36
+
37
+ def self.UInt(value)
38
+ OpenStruct.new(type: "UInt", value: value.to_i)
39
+ end
40
+
41
+ def self.Int8(value)
42
+ OpenStruct.new(type: "Int8", value: value.to_i)
43
+ end
44
+
45
+ def self.UInt8(value)
46
+ OpenStruct.new(type: "UInt8", value: value.to_i)
47
+ end
48
+
49
+ def self.Int16(value)
50
+ OpenStruct.new(type: "Int16", value: value.to_i)
51
+ end
52
+
53
+ def self.UInt16(value)
54
+ OpenStruct.new(type: "UInt16", value: value.to_i)
55
+ end
56
+
57
+ def self.Int32(value)
58
+ OpenStruct.new(type: "Int32", value: value.to_i)
59
+ end
60
+
61
+ def self.UInt32(value)
62
+ OpenStruct.new(type: "UInt32", value: value.to_i)
63
+ end
64
+
65
+ def self.Int64(value)
66
+ OpenStruct.new(type: "Int64", value: value.to_i)
67
+ end
68
+
69
+ def self.UInt64(value)
70
+ OpenStruct.new(type: "UInt64", value: value.to_i)
71
+ end
72
+
73
+ def self.Int64(value)
74
+ OpenStruct.new(type: "Int64", value: value.to_i)
75
+ end
76
+
77
+ def self.UInt64(value)
78
+ OpenStruct.new(type: "UInt64", value: value.to_i)
79
+ end
80
+
81
+ def self.Int128(value)
82
+ OpenStruct.new(type: "Int128", value: value.to_i)
83
+ end
84
+
85
+ def self.UInt128(value)
86
+ OpenStruct.new(type: "UInt128", value: value.to_i)
87
+ end
88
+
89
+ def self.Int256(value)
90
+ OpenStruct.new(type: "Int256", value: value.to_i)
91
+ end
92
+
93
+ def self.UInt256(value)
94
+ OpenStruct.new(type: "UInt256", value: value.to_i)
95
+ end
96
+
97
+ def self.Word8(value)
98
+ OpenStruct.new(type: "Word8", value: value.to_i)
99
+ end
100
+
101
+ def self.Word8(value)
102
+ OpenStruct.new(type: "Word8", value: value.to_i)
103
+ end
104
+
105
+ def self.Word16(value)
106
+ OpenStruct.new(type: "Word16", value: value.to_i)
107
+ end
108
+
109
+ def self.Word16(value)
110
+ OpenStruct.new(type: "Word16", value: value.to_i)
111
+ end
112
+
113
+ def self.Word32(value)
114
+ OpenStruct.new(type: "Word32", value: value.to_i)
115
+ end
116
+
117
+ def self.Word32(value)
118
+ OpenStruct.new(type: "Word32", value: value.to_i)
119
+ end
120
+
121
+ def self.Word64(value)
122
+ OpenStruct.new(type: "Word64", value: value.to_i)
123
+ end
124
+
125
+ def self.Word64(value)
126
+ OpenStruct.new(type: "Word64", value: value.to_i)
127
+ end
128
+
129
+ def self.Fix64(value)
130
+ OpenStruct.new(type: "Fix64", value: value.to_i)
131
+ end
132
+
133
+ def self.Fix64(value)
134
+ OpenStruct.new(type: "Fix64", value: value.to_i)
135
+ end
136
+
137
+ def self.UFix64(value)
138
+ OpenStruct.new(type: "Fix64", value: value.to_i)
139
+ end
140
+
141
+ def self.UFix64(value)
142
+ OpenStruct.new(type: "Fix64", value: value.to_i)
143
+ end
144
+
145
+ def self.Array(values)
146
+ OpenStruct.new(type: "Array", value: values)
147
+ end
148
+
149
+ def self.Dictionary(values)
150
+ OpenStruct.new(type: "Dictionary", value: values)
151
+ end
152
+
153
+ def self.DictionaryValue(key, value)
154
+ OpenStruct.new(key: key, value: value)
155
+ end
156
+
157
+ def self.Path(domain, identifier)
158
+ raise raise ArgumentError.new(
159
+ "Domain can only be one of storage, private or public"
160
+ ) unless ["storage", "private", "public"].include? domain.to_s.downcase
161
+
162
+ OpenStruct.new(
163
+ type: "Path",
164
+ value: OpenStruct.new(domain: domain, identifier: identifier)
165
+ )
166
+ end
167
+
168
+ def self.Type(type_value)
169
+ OpenStruct.new(type: "Type", value: OpenStruct.new(staticType: type_value.to_s))
170
+ end
171
+
172
+ def self.Capability(path, address, borrow_type)
173
+ OpenStruct.new(
174
+ type: "Type",
175
+ value: OpenStruct.new(
176
+ path: path.to_s,
177
+ address: address.to_s,
178
+ borrow_type: borrow_type.to_s
179
+ )
180
+ )
181
+ end
182
+
183
+ def self.Composite(type, value)
184
+ valid_types = [:struct, :resource, :event, :contract, :enum]
185
+ raise ArgumentError.new("incorrect type, expected :struct, :resource, :event, :contract or :enum") unless valid_types.include? type
186
+ OpenStruct.new(type: type.to_s.capitalize, value: value)
187
+ end
188
+
189
+ def self.CompositeValue(id, fields)
190
+ OpenStruct.new(id: id, fields: fields)
191
+ end
192
+
193
+ def self.Field(name, value)
194
+ OpenStruct.new(name: name, value: value)
195
+ end
196
+ end
197
+ end