Skip to content

Commit

Permalink
- update extractors to handle v3 and v4 of 3route
Browse files Browse the repository at this point in the history
- rename stub files to reflect which version it is
- add new stubs
- update tests
  • Loading branch information
simonmcl committed Mar 26, 2024
1 parent 7b9433f commit 910633d
Show file tree
Hide file tree
Showing 7 changed files with 422 additions and 10 deletions.
28 changes: 22 additions & 6 deletions Sources/KukaiCoreSwift/Factories/OperationFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,24 @@ public class OperationFactory {
/**
Extract rpc amount (without decimal info) michelson `execute` value for a 3route call
*/
public static func tokenAmountFromExecuteMichelson(michelson: Any) -> Decimal? {
if let michelsonDict = michelson as? [String: Any] {
public static func tokenAmountFromExecuteMichelson(michelson: Any, contract: String) -> Decimal? {

if contract == "KT1R7WEtNNim3YgkxPt8wPMczjH3eyhbJMtz", let michelsonDict = michelson as? [String: Any] {
// v3

let routeArray = (michelsonDict.michelsonArgsArray()?.michelsonPair(atIndex: 1)?.michelsonArgsArray()?.michelsonPair(atIndex: 1)?.michelsonArgsArray()?.michelsonPair(atIndex: 1)?.michelsonArgsArray()?.michelsonPair(atIndex: 1)?.michelsonArgsUnknownArray()?.first as? [[String: Any]])

var total: Decimal = 0
for michelsonDictRoute in routeArray ?? [] {
let value = michelsonDictRoute.michelsonArgsArray()?.michelsonPair(atIndex: 1)?.michelsonArgsArray()?.michelsonPair(atIndex: 0)?.michelsonArgsArray()?.michelsonInt(atIndex: 0)
total += Decimal(string: value ?? "0") ?? 0
}

return total

} else if contract == "KT1V5XKmeypanMS9pR65REpqmVejWBZURuuT", let michelsonDict = michelson as? [String: Any] {
// v4

let routeArray = (michelsonDict.michelsonArgsArray()?.michelsonPair(atIndex: 1)?.michelsonArgsArray()?.michelsonPair(atIndex: 1)?.michelsonArgsArray()?.michelsonPair(atIndex: 1)?.michelsonArgsArray()?.michelsonPair(atIndex: 1)?.michelsonArgsUnknownArray()?.first as? [[String: Any]])

var total: Decimal = 0
Expand Down Expand Up @@ -594,7 +610,7 @@ public class OperationFactory {
- Approve operation
- update_operator operation
*/
public static func tokenIdAndAmountFromMichelson(michelson: Any) -> (rpcAmount: String, tokenId: Decimal?, destination: String?)? {
public static func tokenIdAndAmountFromMichelson(michelson: Any, contract: String) -> (rpcAmount: String, tokenId: Decimal?, destination: String?)? {
if let michelsonDict = michelson as? [String: Any], let entrypoint = michelsonDict["entrypoint"] as? String {
switch entrypoint {
case OperationTransaction.StandardEntrypoint.approve.rawValue:
Expand All @@ -615,7 +631,7 @@ public class OperationFactory {
return tokenIdAndAmountFromTransferMichelson(michelson: michelsonDict["value"] ?? [:])

case OperationTransaction.StandardEntrypoint.execute.rawValue: // 3route
if let response = tokenAmountFromExecuteMichelson(michelson: michelsonDict["value"] ?? [:]) {
if let response = tokenAmountFromExecuteMichelson(michelson: michelsonDict["value"] ?? [:], contract: contract) {
return (rpcAmount: response.description, tokenId: nil, destination: nil) // Can extract amount, but nothing else

} else {
Expand Down Expand Up @@ -665,7 +681,7 @@ public class OperationFactory {
var lastTokenAddress: String? = nil

for op in operations {
if let opTrans = op as? OperationTransaction, let details = tokenIdAndAmountFromMichelson(michelson: opTrans.parameters ?? [:]), let entrypoint = (opTrans.parameters?["entrypoint"] as? String) {
if let opTrans = op as? OperationTransaction, let details = tokenIdAndAmountFromMichelson(michelson: opTrans.parameters ?? [:], contract: opTrans.destination), let entrypoint = (opTrans.parameters?["entrypoint"] as? String) {

if entrypoint == OperationTransaction.StandardEntrypoint.approve.rawValue || entrypoint == OperationTransaction.StandardEntrypoint.updateOperators.rawValue {

Expand All @@ -676,7 +692,7 @@ public class OperationFactory {
} else if let lastDetails = lastTokenIdAndAmountResults,
let lastTokenAddress = lastTokenAddress,
(entrypoint != OperationTransaction.StandardEntrypoint.approve.rawValue && entrypoint != OperationTransaction.StandardEntrypoint.updateOperators.rawValue),
let knownOpDetails = tokenIdAndAmountFromMichelson(michelson: opTrans.parameters ?? [:]) {
let knownOpDetails = tokenIdAndAmountFromMichelson(michelson: opTrans.parameters ?? [:], contract: opTrans.destination) {

// If we have a previous set of details from an approve or update, check if we can extract something useful from this one to complete the info
return (tokenContract: lastTokenAddress, rpcAmount: knownOpDetails.rpcAmount, tokenId: lastDetails.tokenId, destination: lastDetails.destination ?? "")
Expand Down
33 changes: 29 additions & 4 deletions Tests/KukaiCoreSwiftTests/Factories/OperationFactoryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -627,10 +627,35 @@ class OperationFactoryTests: XCTestCase {
XCTAssert(contractDetails3?.entrypoint == "tezToTokenPayment", contractDetails3?.entrypoint ?? "-")
}

func testExtractors3Route() {
func testExtractors3RouteV3() {
let decoder = JSONDecoder()

let singleRouteJsonData = MockConstants.jsonStub(fromFilename: "3route-single-route")
let fa1ForXTZData = MockConstants.jsonStub(fromFilename: "3route_v3_fa1-for-xtz")
let fa1ForXTZJson = (try? decoder.decode([OperationTransaction].self, from: fa1ForXTZData)) ?? []
XCTAssert(fa1ForXTZJson.count > 0)

let details1 = OperationFactory.Extractor.firstNonZeroTokenTransferAmount(operations: fa1ForXTZJson)
XCTAssert(details1?.tokenContract == "KT1JVjgXPMMSaa6FkzeJcgb8q9cUaLmwaJUX", details1?.tokenContract ?? "-")
XCTAssert(details1?.rpcAmount == "6605336839045864425", details1?.rpcAmount ?? "-")
XCTAssert(details1?.tokenId == nil, details1?.tokenId?.description ?? "-")
XCTAssert(details1?.destination == "KT1R7WEtNNim3YgkxPt8wPMczjH3eyhbJMtz", details1?.destination ?? "-")


let fa2ForXTZData = MockConstants.jsonStub(fromFilename: "3route_v3_fa2-for-xtz")
let fa2ForXTZJson = (try? decoder.decode([OperationTransaction].self, from: fa2ForXTZData)) ?? []
XCTAssert(fa2ForXTZJson.count > 0)

let details2 = OperationFactory.Extractor.firstNonZeroTokenTransferAmount(operations: fa2ForXTZJson)
XCTAssert(details2?.tokenContract == "KT1914CUZ7EegAFPbfgQMRkw8Uz5mYkEz2ui", details2?.tokenContract ?? "-")
XCTAssert(details2?.rpcAmount == "47557742041756", details2?.rpcAmount ?? "-")
XCTAssert(details2?.tokenId == 0, details2?.tokenId?.description ?? "-")
XCTAssert(details2?.destination == "KT1R7WEtNNim3YgkxPt8wPMczjH3eyhbJMtz", details2?.destination ?? "-")
}

func testExtractors3RouteV4() {
let decoder = JSONDecoder()

let singleRouteJsonData = MockConstants.jsonStub(fromFilename: "3route_v4_single-route")
let singleRouteJson = (try? decoder.decode([OperationTransaction].self, from: singleRouteJsonData)) ?? []
XCTAssert(singleRouteJson.count > 0)

Expand All @@ -641,7 +666,7 @@ class OperationFactoryTests: XCTestCase {
XCTAssert(details1?.destination == "KT1V5XKmeypanMS9pR65REpqmVejWBZURuuT", details1?.destination ?? "-")


let multipleRouteJsonData = MockConstants.jsonStub(fromFilename: "3route-multiple-routes")
let multipleRouteJsonData = MockConstants.jsonStub(fromFilename: "3route_v4_multiple-routes")
let multipleRouteJson = (try? decoder.decode([OperationTransaction].self, from: multipleRouteJsonData)) ?? []
XCTAssert(multipleRouteJson.count > 0)

Expand All @@ -652,7 +677,7 @@ class OperationFactoryTests: XCTestCase {
XCTAssert(details2?.destination == "KT1V5XKmeypanMS9pR65REpqmVejWBZURuuT", details2?.destination ?? "-")


let fa1ForFa2Data = MockConstants.jsonStub(fromFilename: "3route-fa1-for-fa2")
let fa1ForFa2Data = MockConstants.jsonStub(fromFilename: "3route_v4_fa1-for-fa2")
let fa1ForFa2Json = (try? decoder.decode([OperationTransaction].self, from: fa1ForFa2Data)) ?? []
XCTAssert(fa1ForFa2Json.count > 0)

Expand Down
121 changes: 121 additions & 0 deletions Tests/KukaiCoreSwiftTests/Stubs/3route_v3_fa1-for-xtz.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
[
{
"amount": "0",
"counter": "24122766",
"destination": "KT1JVjgXPMMSaa6FkzeJcgb8q9cUaLmwaJUX",
"fee": "0",
"gas_limit": "1859",
"kind": "transaction",
"parameters": {
"entrypoint": "approve",
"value": {
"args": [
{
"string": "KT1R7WEtNNim3YgkxPt8wPMczjH3eyhbJMtz"
},
{
"int": "6605336839045864425"
}
],
"prim": "Pair"
}
},
"source": "tz1Nzj8BKu3F6KhyaJYZXEfXkyN51HBNJixi",
"storage_limit": "18"
},
{
"amount": "0",
"counter": "24122767",
"destination": "KT1R7WEtNNim3YgkxPt8wPMczjH3eyhbJMtz",
"fee": "3585",
"gas_limit": "28887",
"kind": "transaction",
"parameters": {
"entrypoint": "execute",
"value": {
"args": [
{
"int": "77"
},
{
"args": [
{
"int": "0"
},
{
"args": [
{
"int": "9299"
},
{
"args": [
{
"string": "tz1Nzj8BKu3F6KhyaJYZXEfXkyN51HBNJixi"
},
{
"args": [
[
{
"args": [
{
"int": "0"
},
{
"args": [
{
"args": [
{
"int": "6605336839045864425"
}
],
"prim": "Some"
},
{
"args": [
{
"int": "377"
},
{
"args": [
{
"int": "3"
},
{
"bytes": ""
}
],
"prim": "Pair"
}
],
"prim": "Pair"
}
],
"prim": "Pair"
}
],
"prim": "Elt"
}
],
{
"int": "3"
}
],
"prim": "Pair"
}
],
"prim": "Pair"
}
],
"prim": "Pair"
}
],
"prim": "Pair"
}
],
"prim": "Pair"
}
},
"source": "tz1Nzj8BKu3F6KhyaJYZXEfXkyN51HBNJixi",
"storage_limit": "0"
}
]
Loading

0 comments on commit 910633d

Please sign in to comment.