-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add oracle contract written by ont smartcontract
- Loading branch information
Showing
12 changed files
with
1,635 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
############ Chainlink Library######### | ||
from ontology.interop.System.App import RegisterAppCall | ||
|
||
defaultBufferSize = 256 | ||
BufferCall = RegisterAppCall('d5f12664535717af51f52fe2aa88a18d327ea1b9', 'operation', 'args') | ||
CBORCall = RegisterAppCall('3f75e2814021abed8a616da8d408d1347cac988f', 'operation', 'args') | ||
|
||
|
||
def Main(operation, args): | ||
if operation == 'initialize': | ||
assert (len(args) == 3) | ||
id = args[0] | ||
callbackAddress = args[1] | ||
callbackFunction = args[2] | ||
return initialize(id, callbackAddress, callbackFunction) | ||
|
||
if operation == 'setBuffer': | ||
assert (len(args) == 2) | ||
request = args[0] | ||
data = args[1] | ||
return setBuffer(request, data) | ||
|
||
if operation == 'add': | ||
assert (len(args) == 3) | ||
request = args[0] | ||
key = args[1] | ||
value = args[2] | ||
return add(request, key, value) | ||
|
||
if operation == 'addBytes': | ||
assert (len(args) == 3) | ||
request = args[0] | ||
key = args[1] | ||
value = args[2] | ||
return addBytes(request, key, value) | ||
|
||
if operation == 'addUInt': | ||
assert (len(args) == 3) | ||
request = args[0] | ||
key = args[1] | ||
value = args[2] | ||
return addUInt(request, key, value) | ||
|
||
if operation == 'addInt': | ||
assert (len(args) == 3) | ||
request = args[0] | ||
key = args[1] | ||
value = args[2] | ||
return addInt(request, key, value) | ||
|
||
if operation == 'addStringArray': | ||
assert (len(args) == 3) | ||
request = args[0] | ||
key = args[1] | ||
values = args[2] | ||
return addStringArray(request, key, values) | ||
|
||
return True | ||
|
||
|
||
def initialize(id, callbackAddress, callbackFunction): | ||
return [id, callbackAddress, callbackFunction, 0, None] | ||
|
||
|
||
def setBuffer(request, data): | ||
request[4] = BufferCall('WriteBytes', [data, request[4]]) | ||
return [request[0], request[1], request[2], request[3], request[4]] | ||
|
||
|
||
def add(request, key, value): | ||
request[4] = CBORCall('encodeString', [request[4], key]) | ||
request[4] = CBORCall('encodeString', [request[4], value]) | ||
return [request[0], request[1], request[2], request[3], request[4]] | ||
|
||
|
||
def addBytes(request, key, value): | ||
request[4] = CBORCall('encodeString', [request[4], key]) | ||
request[4] = CBORCall('encodeBytes', [request[4], value]) | ||
return [request[0], request[1], request[2], request[3], request[4]] | ||
|
||
|
||
def addInt(request, key, value): | ||
request[4] = CBORCall('encodeString', [request[4], key]) | ||
request[4] = CBORCall('encodeInt', [request[4], value]) | ||
return [request[0], request[1], request[2], request[3], request[4]] | ||
|
||
|
||
def addUInt(request, key, value): | ||
request[4] = CBORCall('encodeString', [request[4], key]) | ||
request[4] = CBORCall('encodeUInt', [request[4], value]) | ||
return [request[0], request[1], request[2], request[3], request[4]] | ||
|
||
|
||
def addStringArray(request, key, values): | ||
request[4] = CBORCall('encodeString', [request[4], key]) | ||
request[4] = CBORCall('startArray', [request[4]]) | ||
for i in range(len(values)): | ||
request[4] = CBORCall('encodeString', [request[4], values[i]]) | ||
request[4] = CBORCall('endSequence', [request[4]]) | ||
return [request[0], request[1], request[2], request[3], request[4]] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
from ontology.builtins import sha256, concat | ||
from ontology.interop.Ontology.Runtime import Base58ToAddress | ||
from ontology.interop.System.Action import RegisterAction | ||
from ontology.interop.System.App import DynamicAppCall, RegisterAppCall | ||
from ontology.interop.System.ExecutionEngine import GetExecutingScriptHash, GetCallingScriptHash | ||
from ontology.interop.System.Runtime import CheckWitness, Serialize, Notify | ||
from ontology.interop.System.Storage import GetContext, Get, Put, Delete | ||
from ontology.libont import bytearray_reverse | ||
# bb7513b23fae0117eae21eea2cd732e1cc267e7e | ||
AMOUNT_OVERRIDE = 0 | ||
|
||
SENDER_OVERRIDE = 0 | ||
|
||
ARGS_VERSION = 1 | ||
|
||
REQUEST_COUNT = "RequestCount" | ||
|
||
ORACLE_ADDRESS = "oracle" | ||
LINK_ADDRESS = "link" | ||
|
||
PENDING_REQUESTS_PREFIX = "pendingRequests" | ||
|
||
contractHash = GetExecutingScriptHash() | ||
|
||
ChainlinkRequestedEvent = RegisterAction("chainlinkRequestedEvent", "requestId") | ||
|
||
ChainlinkFulfilledEvent = RegisterAction("chainlinkFulfilledEvent", "requestId") | ||
|
||
ChainlinkCancelledEvent = RegisterAction("chainlinkCancelledEvent", "requestId") | ||
|
||
ChainlinkCall = RegisterAppCall('db6f26fb0f217d6762aa3d6d38e827789a3128d1', 'operation', 'args') | ||
|
||
OWNER = Base58ToAddress("AbG3ZgFrMK6fqwXWR1WkQ1d1EYVunCwknu") | ||
|
||
def Main(operation, args): | ||
if operation == 'buildChainlinkRequest': | ||
assert (len(args) == 3) | ||
_specId = args[0] | ||
callbackAddress = args[1] | ||
callbackFunction = args[2] | ||
return buildChainlinkRequest(_specId, callbackAddress, callbackFunction) | ||
|
||
if operation == 'sendChainlinkRequest': | ||
assert (len(args) == 3) | ||
caller = args[0] | ||
req = args[1] | ||
payment = args[2] | ||
return sendChainlinkRequest(caller, req, payment) | ||
|
||
if operation == 'sendChainlinkRequestTo': | ||
assert (len(args) == 4) | ||
caller = args[0] | ||
oracle = args[1] | ||
req = args[2] | ||
payment = args[3] | ||
return sendChainlinkRequestTo(caller, oracle, req, payment) | ||
|
||
if operation == 'cancelChainlinkRequest': | ||
assert (len(args) == 5) | ||
sender = args[0] | ||
requestId = args[1] | ||
payment = args[2] | ||
callbackFunctionId = args[3] | ||
expiration = args[4] | ||
return cancelChainlinkRequest(sender, requestId, payment, callbackFunctionId, expiration) | ||
|
||
if operation == 'setChainlinkOracle': | ||
assert (len(args) == 1) | ||
oracle = args[0] | ||
return setChainlinkOracle(oracle) | ||
|
||
if operation == 'setChainlinkToken': | ||
assert (len(args) == 1) | ||
link = args[0] | ||
return setChainlinkToken(link) | ||
|
||
if operation == 'chainlinkTokenAddress': | ||
return chainlinkTokenAddress() | ||
|
||
if operation == 'chainlinkOracleAddress': | ||
return chainlinkOracleAddress() | ||
|
||
if operation == 'addChainlinkExternalRequest': | ||
assert (len(args) == 2) | ||
oracle = args[0] | ||
requestId = args[1] | ||
return addChainlinkExternalRequest(oracle, requestId) | ||
|
||
if operation == 'recordChainlinkFulfillment': | ||
assert (len(args) == 2) | ||
sender = args[0] | ||
requestId = args[1] | ||
return recordChainlinkFulfillment(sender, requestId) | ||
|
||
return False | ||
|
||
|
||
def buildChainlinkRequest(_specId, callbackAddress, callbackFunction): | ||
return ChainlinkCall('initialize', [_specId, callbackAddress, callbackFunction]) | ||
|
||
|
||
def sendChainlinkRequest(caller, req, payment): | ||
return sendChainlinkRequestTo(caller, Get(GetContext(), ORACLE_ADDRESS), req, payment) | ||
|
||
def sendChainlinkRequestTo(caller, oracle, req, payment): | ||
RequireWitness(caller) | ||
requestCount = Get(GetContext(), REQUEST_COUNT) | ||
requestId = sha256(Serialize([req[1], caller, requestCount])) | ||
req[3] = requestCount | ||
Put(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId), oracle) | ||
ChainlinkRequestedEvent(requestId) | ||
link = Get(GetContext(), LINK_ADDRESS) | ||
|
||
params = [caller, oracle, payment, | ||
[SENDER_OVERRIDE, AMOUNT_OVERRIDE, req[0], req[1], req[2], req[3], ARGS_VERSION, req[4], 'oracleRequest']] | ||
assert (DynamicCallFunction(bytearray_reverse(link), "transferAndCall", params)) | ||
|
||
Put(GetContext(), REQUEST_COUNT, requestCount + 1) | ||
return True | ||
|
||
|
||
def cancelChainlinkRequest(sender, requestId, payment, callbackFunctionId, expiration): | ||
RequireWitness(sender) | ||
oracle = Get(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId)) | ||
params = [sender, requestId, payment, GetCallingScriptHash(), callbackFunctionId, expiration] | ||
assert (DynamicCallFunction(bytearray_reverse(oracle), "cancelOracleRequest", params)) | ||
Delete(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId)) | ||
ChainlinkCancelledEvent(requestId) | ||
return True | ||
|
||
|
||
def setChainlinkOracle(oracle): | ||
RequireWitness(OWNER) | ||
assert (len(oracle) == 20) | ||
Put(GetContext(), ORACLE_ADDRESS, oracle) | ||
return True | ||
|
||
|
||
def setChainlinkToken(link): | ||
RequireWitness(OWNER) | ||
assert (len(link) == 20) | ||
Put(GetContext(), LINK_ADDRESS, link) | ||
return True | ||
|
||
|
||
def chainlinkTokenAddress(): | ||
return Get(GetContext(), LINK_ADDRESS) | ||
|
||
|
||
def chainlinkOracleAddress(): | ||
return Get(GetContext(), ORACLE_ADDRESS) | ||
|
||
|
||
def addChainlinkExternalRequest(oracle, requestId): | ||
assert (notPendingRequest(requestId)) | ||
Put(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId), oracle) | ||
return True | ||
|
||
|
||
## TODO | ||
def useChainlinkWithENS(ens, node): | ||
return True | ||
|
||
|
||
## TODO | ||
def updateChainlinkOracleWithENS(): | ||
return True | ||
|
||
|
||
def recordChainlinkFulfillment(sender, requestId): | ||
assert (sender == Get(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId))) | ||
# Notify([sender, Get(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId))]) | ||
Delete(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId)) | ||
ChainlinkFulfilledEvent(requestId) | ||
return True | ||
|
||
|
||
def notPendingRequest(requestId): | ||
assert (not Get(GetContext(), concatKey(PENDING_REQUESTS_PREFIX, requestId))) | ||
return True | ||
|
||
|
||
def concatKey(str1, str2): | ||
return concat(concat(str1, '_'), str2) | ||
|
||
|
||
def RequireScriptHash(key): | ||
assert (len(key) == 20) | ||
return True | ||
|
||
|
||
def RequireWitness(witness): | ||
assert (CheckWitness(witness)) | ||
return True | ||
|
||
|
||
def DynamicCallFunction(callAddress, callbackFunctionId, params): | ||
res = DynamicAppCall(callAddress, callbackFunctionId, params) | ||
if res and res == b'\x01': | ||
return True | ||
else: | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
from ontology.builtins import concat | ||
from ontology.interop.Ontology.Runtime import Base58ToAddress | ||
from ontology.interop.System.App import RegisterAppCall, DynamicAppCall | ||
from ontology.interop.System.ExecutionEngine import GetExecutingScriptHash, GetCallingScriptHash | ||
from ontology.interop.System.Runtime import CheckWitness, Notify | ||
from ontology.interop.System.Storage import GetContext, Put, Get | ||
from ontology.libont import bytearray_reverse | ||
|
||
CURRENT_PRICE = 'CurrentPrice' | ||
|
||
OWNER = Base58ToAddress('AbG3ZgFrMK6fqwXWR1WkQ1d1EYVunCwknu') | ||
|
||
ChainlinkCall = RegisterAppCall('db6f26fb0f217d6762aa3d6d38e827789a3128d1', 'operation', 'args') | ||
ChainlinkClientCall = RegisterAppCall('da8aed3a33ba8e7159a991070ea19002ebb06c6f', 'operation', 'args') | ||
|
||
ContractAddress = GetExecutingScriptHash() | ||
|
||
|
||
def Main(operation, args): | ||
if operation == 'requestEthereumPrice': | ||
assert (len(args) == 3) | ||
oracle = args[0] | ||
jobId = args[1] | ||
payment = args[2] | ||
return requestEthereumPrice(oracle, jobId, payment) | ||
|
||
if operation == 'fulfill': | ||
assert (len(args) == 2) | ||
requestId = args[0] | ||
price = args[1] | ||
return fulfill(requestId, price) | ||
|
||
if operation == 'getCurrentPrice': | ||
return getCurrentPrice() | ||
|
||
if operation == 'cancelRequest': | ||
assert (len(args) == 4) | ||
requestId = args[0] | ||
payment = args[1] | ||
callBackFunc = args[2] | ||
expiration = args[3] | ||
return cancelRequest(requestId, payment, callBackFunc, expiration) | ||
|
||
return False | ||
|
||
|
||
def requestEthereumPrice(oracle, jobId, payment): | ||
assert (CheckWitness(OWNER)) | ||
req = ChainlinkClientCall('buildChainlinkRequest', [jobId, ContractAddress, 'fulfill']) | ||
req = ChainlinkCall('add', [req, "get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD"]) | ||
req = ChainlinkCall('add', [req, "path", "USD"]) | ||
req = ChainlinkCall('addInt', [req, "times", 100]) | ||
# Notify([OWNER, oracle, req, payment]) | ||
assert (ChainlinkClientCall('sendChainlinkRequestTo', [OWNER, oracle, req, payment])) | ||
return True | ||
|
||
|
||
def fulfill(requestId, price): | ||
assert (ChainlinkClientCall('recordChainlinkFulfillment', [bytearray_reverse(GetCallingScriptHash()), requestId])) | ||
# Notify(['test']) | ||
Put(GetContext(), CURRENT_PRICE, price) | ||
return True | ||
|
||
|
||
def getCurrentPrice(): | ||
return Get(GetContext(), CURRENT_PRICE) | ||
|
||
|
||
def cancelRequest(requestId, payment, callBackFunc, expiration): | ||
assert (CheckWitness(OWNER)) | ||
assert (ChainlinkClientCall('cancelChainlinkRequest', [OWNER, requestId, payment, callBackFunc, expiration])) | ||
return True | ||
|
||
|
||
def concatKey(str1, str2): | ||
return concat(concat(str1, '_'), str2) | ||
|
||
|
||
def DynamicCallFunction(callAddress, callbackFunctionId, params): | ||
res = DynamicAppCall(callAddress, callbackFunctionId, params) | ||
if res and res == b'\x01': | ||
return True | ||
else: | ||
return False | ||
|
||
|
||
def DynamicCallFunctionResult(callAddress, callbackFunctionId, params): | ||
return DynamicAppCall(callAddress, callbackFunctionId, params) |
Oops, something went wrong.