def update(self, params):
        # If there is no value for the public key, the oracle is revoked. Ignore updates.
        sp.verify(self.data.publicKey.is_some(), "revoked")

        # Iterate over assets in the input map.
        keyValueList = params.items()
        sp.for assetData in keyValueList:
            # Extract asset names, signatures, and the new data.
            assetName = assetData.key
            signature = sp.compute(sp.fst(assetData.value))
            newData = sp.compute(sp.snd(assetData.value))

            # Verify Oracle is tracking this asset.
            sp.if self.data.oracleData.contains(assetName):
                # Verify start timestamp is newer than the last update.
                oldData = sp.compute(self.data.oracleData[assetName])
                oldStartTime = sp.compute(sp.fst(oldData))
                newStartTime = sp.compute(sp.fst(newData))    
                sp.if newStartTime > oldStartTime:                
                    # Verify signature.
                    bytes = sp.pack((assetName, newData))
                    sp.verify(
                        sp.check_signature(
                            self.data.publicKey.open_some(), signature, bytes
                        ),
                        "bad sig"
                    )

                    # Replace the data.
                    self.data.oracleData[assetName] = newData
Beispiel #2
0
 def token_metadata(self, params):
     sp.verify( ~self.is_paused() )
     sp.set_type(params,
                 sp.TRecord(
                     token_ids = sp.TList(sp.TNat),
                     handler = sp.TLambda(
                         sp.TList(self.token_meta_data.get_type()),
                         sp.TUnit)
                 ).layout(("token_ids", "handler")))
     def f_on_request(req):
         self.token_meta_data.set_type_and_layout(self.data.token_metadata[req])
         sp.result(self.data.token_metadata[req])
     sp.compute(params.handler(params.token_ids.map(f_on_request)))
 def receiveNft(self, nft):
     sp.set_type(nft, sp.TTicket(sp.TNat))
     ticket_data, ticket_next = sp.read_ticket(nft)
     qty = sp.compute(sp.snd(sp.snd(ticket_data)))
     originator = sp.compute(sp.fst(ticket_data))
     id = sp.compute(sp.fst(sp.snd(ticket_data)))
     sp.verify(qty == 1, "Only send 1 Nft to this entrypoint")
     sp.verify(sp.source == self.data.admin,
               "Ticket needs to be sent by wallet admin")
     current_id = self.data.current_id
     new_map = sp.update_map(self.data.tickets, current_id,
                             sp.some(ticket_next))
     self.data.tickets = new_map
     self.data.current_id = current_id + 1
    def update(self, updateMap):
        sp.set_type(updateMap, sp.TBigMap(sp.TString, Harbinger.OracleDataType))

        # Verify the sender is the whitelisted oracle contract.
        sp.verify(
            sp.sender == self.data.oracleContract,
            message="bad sender"
        )

        # Iterate over assets this normalizer is tracking
        sp.for assetCode in self.data.assetCodes:
            # Only process updates if this normalizer is tracking the asset code.
            sp.if updateMap.contains(assetCode):
                assetData = updateMap.get(assetCode)

                # Only process updates that are monotonically increasing in start times.
                updateStartTime = sp.compute(sp.fst(assetData))
                sp.if updateStartTime > self.data.assetMap[assetCode].lastUpdateTime:
                    # Extract required information
                    endPair = sp.compute(sp.snd(assetData))
                    openPair = sp.compute(sp.snd(endPair))
                    highPair = sp.compute(sp.snd(openPair))
                    lowPair = sp.compute(sp.snd(highPair))
                    closeAndVolumePair = sp.compute(sp.snd(lowPair))

                    high = sp.compute(sp.fst(highPair))
                    low = sp.compute(sp.fst(lowPair))
                    close = sp.compute(sp.fst(closeAndVolumePair))
                    volume = sp.compute(sp.snd(closeAndVolumePair))

                    # Ignore candles with zero volumes.
                    sp.if volume > 0:
                        # Calculate the the price for this data point.
                        # average price * volume
                        volumePrice = ((high + low + close) / 3) * volume

                        # Update the last updated time.
                        self.data.assetMap[assetCode].lastUpdateTime = updateStartTime

                        # Push the latest items to the FIFO queue
                        fifoDT.push(self.data.assetMap[assetCode].prices, volumePrice)
                        fifoDT.push(self.data.assetMap[assetCode].volumes, volume)

                        # Trim the queue if it exceeds the number of data points.
                        sp.if fifoDT.len(self.data.assetMap[assetCode].prices) > self.data.numDataPoints:
                            fifoDT.pop(self.data.assetMap[assetCode].prices)
                            fifoDT.pop(self.data.assetMap[assetCode].volumes)
    def get(self, requestPair):
        sp.set_type(requestPair, sp.TPair(sp.TString, sp.TContract(sp.TPair(sp.TString, sp.TPair(sp.TTimestamp, sp.TNat)))))

        # Destructure the arguments.
        requestedAsset = sp.compute(sp.fst(requestPair))
        callback = sp.compute(sp.snd(requestPair))

        # Verify this normalizer has data for the requested asset.
        sp.verify(
            self.data.assetMap.contains(requestedAsset),
            message="bad request"
        )

        # Callback with the requested data.
        assetData = self.data.assetMap[requestedAsset]
        normalizedPrice = assetData.computedPrice
        lastUpdateTime = assetData.lastUpdateTime
        callbackParam = (requestedAsset, (lastUpdateTime, normalizedPrice))
        sp.transfer(callbackParam, sp.mutez(0), callback)
Beispiel #6
0
 def cancel_request(self, client_request_id):
     # We do not want to check active here (it would be bad for the client).
     # sp.sender needs to be validated; this process is done through the use of the reverse_request_key.
     reverse_request_key = sp.compute(sp.record(client = sp.sender, client_request_id = client_request_id))
     request_id = sp.local('request_id', self.data.reverse_requests[reverse_request_key]).value
     request = sp.local('request', self.data.requests[request_id]).value
     sp.verify(request.timeout <= sp.now, message = "TTL not met")
     token = sp.contract(self.token_contract.batch_transfer.get_type(), self.data.token, entry_point = "transfer").open_some(message = "Incompatible token interface")
     sp.transfer([sp.record(from_ = sp.to_address(sp.self), txs = [sp.record(to_ = request.client, token_id = 0, amount = request.amount)])],
                 sp.tez(0),
                 token)
     del self.data.requests[request_id]
     del self.data.reverse_requests[reverse_request_key]
Beispiel #7
0
 def create_request(self, client, params):
     sp.verify(sp.sender == self.data.token, message = "Invalid source")
     sp.verify(self.data.active, message = "Inactive")
     amount         = params.amount
     target         = params.target
     job_id         = params.job_id
     parameters     = params.parameters
     timeout        = params.timeout
     sp.verify(self.data.min_amount <= amount, message = "Invalid payment")
     sp.verify(sp.now.add_minutes(self.data.min_timeout_minutes) <= timeout, message = "Invalid timeout")
     client_request_id  = params.client_request_id
     new_request = sp.record(client            = client,
                             target            = target,
                             job_id            = job_id,
                             parameters        = parameters,
                             amount            = amount,
                             timeout           = timeout,
                             client_request_id = client_request_id)
     reverse_request_key = sp.compute(sp.record(client = client, client_request_id = client_request_id))
     sp.verify(~self.data.reverse_requests.contains(reverse_request_key), message = "Bad request key")
     self.data.reverse_requests[reverse_request_key] = self.data.next_id
     self.data.requests[self.data.next_id] = new_request
     self.data.next_id += 1
Beispiel #8
0
 def collect(self, amount):
     sp.verify(sp.sender == self.data.owner, 'Only owner can collect.')
     max_collect = sp.compute(sp.split_tokens(sp.balance,sp.nat(100),self.data.max_collect_percent))
     sp.verify(amount <= max_collect, 'Withdrawal amount exceeds allowed limit.')
     sp.if (self.data.next_collect.is_some()):
         sp.verify(sp.some(sp.now) > self.data.next_collect, 'Withdrawal frequency exceeds limit.')