-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: CreateOracle, ListenOracleQueries higher level convenience f…
…unctions. New naet.Node capability required: GetOracleQueriesByPubkey
- Loading branch information
1 parent
9217c01
commit 8b3d66d
Showing
6 changed files
with
166 additions
and
4 deletions.
There are no files selected for viewing
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
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
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
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,57 @@ | ||
package aeternity | ||
|
||
import ( | ||
"math/big" | ||
"strings" | ||
"time" | ||
|
||
"github.com/aeternity/aepp-sdk-go/v7/account" | ||
"github.com/aeternity/aepp-sdk-go/v7/config" | ||
"github.com/aeternity/aepp-sdk-go/v7/naet" | ||
"github.com/aeternity/aepp-sdk-go/v7/swagguard/node/models" | ||
"github.com/aeternity/aepp-sdk-go/v7/transactions" | ||
) | ||
|
||
// CreateOracle registers a new oracle with the given queryspec and responsespec | ||
func CreateOracle(n naet.NodeInterface, oracleAccount *account.Account, queryspec, responsespec string, queryFee *big.Int, queryTTLType uint64, oracleTTL uint64) (oracleID string, err error) { | ||
var oraclizer = strings.NewReplacer("ak_", "ok_") | ||
networkID, err := getNetworkID(n) | ||
if err != nil { | ||
return | ||
} | ||
_, _, ttlnoncer := transactions.GenerateTTLNoncer(n) | ||
registerTx, err := transactions.NewOracleRegisterTx(oracleAccount.Address, queryspec, responsespec, queryFee, queryTTLType, oracleTTL, config.Client.Oracles.ABIVersion, ttlnoncer) | ||
if err != nil { | ||
return | ||
} | ||
|
||
_, _, _, _, _, err = SignBroadcastWaitTransaction(registerTx, oracleAccount, n, networkID, config.Client.WaitBlocks) | ||
if err != nil { | ||
return | ||
} | ||
return oraclizer.Replace(oracleAccount.Address), nil | ||
} | ||
|
||
// ListenOracleQueries polls the node at a custom interval and returns queries | ||
// and errors in their respective channels. listenInterval should be specified | ||
// in milliseconds. | ||
func ListenOracleQueries(n naet.GetOracleQueriesByPubkeyer, oracleID string, queryChan chan *models.OracleQuery, errChan chan error, listenInterval time.Duration) (err error) { | ||
// Node always returns all queries, but keeping track of until where we read | ||
// last iteration ensures we only report newly arriving queries. This means | ||
// the first time this loop runs, it will always return all the queries to | ||
// an oracle. | ||
var readUntilPosition int | ||
for { | ||
oQueries, err := n.GetOracleQueriesByPubkey(oracleID) | ||
if err != nil { | ||
errChan <- err | ||
} else { | ||
for _, q := range oQueries.OracleQueries[readUntilPosition:] { | ||
queryChan <- q | ||
readUntilPosition++ | ||
} | ||
} | ||
|
||
time.Sleep(listenInterval * time.Millisecond) | ||
} | ||
} |
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,87 @@ | ||
package aeternity | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
"time" | ||
|
||
"github.com/aeternity/aepp-sdk-go/v7/swagguard/node/models" | ||
) | ||
|
||
type mockOracleQueryNode struct { | ||
oracleQueries *models.OracleQueries | ||
Count int | ||
} | ||
|
||
func newMockOracleQueryNode() *mockOracleQueryNode { | ||
return &mockOracleQueryNode{ | ||
oracleQueries: &models.OracleQueries{ | ||
OracleQueries: []*models.OracleQuery{}, | ||
}, | ||
} | ||
} | ||
func (m *mockOracleQueryNode) GetOracleQueriesByPubkey(pubkey string) (oracleQueries *models.OracleQueries, err error) { | ||
return m.oracleQueries, err | ||
} | ||
func newOracleQuery(i int) (q *models.OracleQuery, err error) { | ||
q = new(models.OracleQuery) | ||
qJSON := fmt.Sprintf(`{"fee":%d,"id":"oq_FAKEQUERY","oracle_id":"ok_FAKEID","query":"ov_FAKEQUERY=","response":"or_FAKERESPONSE","response_ttl":{"type":"delta","value":100},"sender_id":"ak_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi","sender_nonce":%d,"ttl":137}`, i, i) | ||
err = q.UnmarshalBinary([]byte(qJSON)) | ||
return | ||
} | ||
|
||
func (m *mockOracleQueryNode) AddOracleQuery(n int) (err error) { | ||
// Create some fake OracleQuerys to add them to | ||
// mockOracleQueryNode.OracleQueries. Keep track of how many we have | ||
// created. | ||
for index := 0; index < n; index++ { | ||
q, err := newOracleQuery(m.Count) | ||
if err != nil { | ||
break | ||
} | ||
m.Count++ | ||
m.oracleQueries.OracleQueries = append(m.oracleQueries.OracleQueries, q) | ||
} | ||
return | ||
} | ||
|
||
func TestListenOracleQueries(t *testing.T) { | ||
n := newMockOracleQueryNode() | ||
|
||
oQueries := make(chan *models.OracleQuery, 30) | ||
errChan := make(chan error) | ||
go ListenOracleQueries(n, "ok_FAKEID", oQueries, errChan, 20) | ||
n.AddOracleQuery(3) | ||
n.AddOracleQuery(5) | ||
time.Sleep(20 * time.Millisecond) | ||
n.AddOracleQuery(15) | ||
time.Sleep(20 * time.Millisecond) | ||
t.Logf("oQueries channel contains %d queries; we generated %d\n", len(oQueries), n.Count) | ||
if n.Count != len(oQueries) { | ||
t.Fatalf("Oracle Queries channel should contain %d queries but actually had %d", n.Count, len(oQueries)) | ||
} | ||
} | ||
|
||
func TestManyPendingOracleQueries(t *testing.T) { | ||
n := newMockOracleQueryNode() | ||
readQueries := []*models.OracleQuery{} | ||
oQueries := make(chan *models.OracleQuery, 5) | ||
errChan := make(chan error) | ||
|
||
n.AddOracleQuery(100) | ||
|
||
go ListenOracleQueries(n, "ok_FAKEID", oQueries, errChan, 20) | ||
|
||
var q *models.OracleQuery | ||
for i := 0; i < 100; i++ { | ||
q = <-oQueries | ||
readQueries = append(readQueries, q) | ||
} | ||
|
||
if len(oQueries) != 0 { | ||
t.Fatalf("oQueries channel should be empty but still contains %d queries", len(oQueries)) | ||
} | ||
if len(readQueries) != 100 { | ||
t.Fatalf("We should have 100 queries in readQueries but instead we have %d queries", len(readQueries)) | ||
} | ||
} |
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