Skip to content

Commit a3143a8

Browse files
authored
Normalizer versioning fix (#1785)
* Normalizer versioning fix * Fix error * add logic to find newest service * Add util-semver package * Move logic to normalizeServices
1 parent cc21dbf commit a3143a8

25 files changed

+367
-96
lines changed

.changeset/early-olives-explode.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@onflow/fcl": patch
3+
---
4+
5+
Fix version normalization of services in FCL

package-lock.json

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/fcl/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,15 @@
6767
"@onflow/util-address": "^1.1.0",
6868
"@onflow/util-invariant": "^1.1.0",
6969
"@onflow/util-logger": "^1.2.2",
70+
"@onflow/util-semver": "^1.0.0",
7071
"@onflow/util-template": "^1.1.0",
7172
"@onflow/util-uid": "^1.1.0",
7273
"cross-fetch": "^3.1.6"
7374
},
7475
"peerDependencies": {
7576
"@react-native-async-storage/async-storage": "^1.13.0",
76-
"expo-web-browser": "^12.0.0",
7777
"expo-linking": "^4.0.0",
78+
"expo-web-browser": "^12.0.0",
7879
"react": "^17.0.0 || ^18.0.0",
7980
"react-native": "^0.0.0-0 || 0.60 - 0.72 || 1000.0.0"
8081
},

packages/fcl/src/current-user/build-user.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import * as rlp from "@onflow/rlp"
33
import {fetchServices} from "./fetch-services"
44
import {mergeServices} from "./merge-services"
55
import {USER_PRAGMA} from "../normalizers/service/__vsn"
6-
import {normalizeService} from "../normalizers/service/service"
6+
import {
7+
normalizeService,
8+
normalizeServices,
9+
} from "../normalizers/service/service"
10+
import {serviceOfType} from "./service-of-type"
711

812
function deriveCompositeId(authn) {
913
return rlp
@@ -20,19 +24,14 @@ function normalizeData(data) {
2024
return data
2125
}
2226

23-
function findService(type, services) {
24-
return services.find(d => d.type === type)
25-
}
26-
2727
export async function buildUser(data) {
2828
data = normalizeData(data)
2929

30-
var services = mergeServices(
31-
data.services || [],
32-
await fetchServices(data.hks, data.code)
33-
).map(service => normalizeService(service, data))
30+
var services = normalizeServices(
31+
mergeServices(data.services || [], await fetchServices(data.hks, data.code))
32+
)
3433

35-
const authn = findService("authn", services)
34+
const authn = serviceOfType(services, "authn")
3635

3736
return {
3837
...USER_PRAGMA,

packages/fcl/src/current-user/merge-services.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import {withPrefix} from "@onflow/util-address"
2-
31
export function mergeServices(sx1 = [], sx2 = []) {
42
// TODO: Make this smarter
53
return [...sx1, ...sx2]
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
import * as semver from "@onflow/util-semver"
2+
13
export function serviceOfType(services = [], type) {
2-
return services.find(service => service.type === type)
4+
// Find the greatest version of the service type
5+
return services.reduce(
6+
(mostRecent, service) =>
7+
service.type === type
8+
? !mostRecent || semver.compare(service.f_vsn, mostRecent.f_vsn) > 0
9+
? service
10+
: mostRecent
11+
: mostRecent,
12+
null
13+
)
314
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {serviceOfType} from "./service-of-type"
2+
3+
describe("service-of-type", () => {
4+
it("should choose the most recent version of a service", () => {
5+
const services = [
6+
{
7+
type: "authn",
8+
f_vsn: "1.0.0",
9+
},
10+
{
11+
type: "authn",
12+
f_vsn: "2.0.0",
13+
},
14+
]
15+
16+
const service = serviceOfType(services, "authn")
17+
18+
expect(service).toEqual({
19+
type: "authn",
20+
f_vsn: "2.0.0",
21+
})
22+
})
23+
24+
it("should return null if no service of type exists", () => {
25+
const services = [
26+
{
27+
type: "authn",
28+
f_vsn: "1.0.0",
29+
},
30+
{
31+
type: "authn",
32+
f_vsn: "2.0.0",
33+
},
34+
]
35+
36+
const service = serviceOfType(services, "non-existent")
37+
38+
expect(service).toBe(null)
39+
})
40+
})

packages/fcl/src/normalizers/service/account-proof.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,15 @@
1515
export function normalizeAccountProof(service) {
1616
if (service == null) return null
1717

18+
if (!service["f_vsn"]) {
19+
throw new Error(`FCL Normalizer Error: Invalid account-proof service`)
20+
}
21+
1822
switch (service["f_vsn"]) {
1923
case "1.0.0":
2024
return service
2125

2226
default:
23-
throw new Error(`FCL Normalizer Error: Invalid account-proof service`)
27+
return null
2428
}
2529
}

packages/fcl/src/normalizers/service/authn-refresh.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@
1212
export function normalizeAuthnRefresh(service) {
1313
if (service == null) return null
1414

15+
if (!service["f_vsn"]) {
16+
throw new Error("Invalid authn-refresh service")
17+
}
18+
1519
switch (service["f_vsn"]) {
1620
case "1.0.0":
1721
return service
1822

1923
default:
20-
throw new Error("Invalid authn-refresh service")
24+
return null
2125
}
2226
}

packages/fcl/src/normalizers/service/authn.js

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,26 @@ import {SERVICE_PRAGMA} from "./__vsn"
2121
export function normalizeAuthn(service) {
2222
if (service == null) return null
2323

24+
if (!service["f_vsn"]) {
25+
return {
26+
...SERVICE_PRAGMA,
27+
type: service.type,
28+
uid: service.id,
29+
endpoint: service.authn,
30+
id: service.pid,
31+
provider: {
32+
address: withPrefix(service.addr),
33+
name: service.name,
34+
icon: service.icon,
35+
},
36+
}
37+
}
38+
2439
switch (service["f_vsn"]) {
2540
case "1.0.0":
2641
return service
2742

2843
default:
29-
return {
30-
...SERVICE_PRAGMA,
31-
type: service.type,
32-
uid: service.id,
33-
endpoint: service.authn,
34-
id: service.pid,
35-
provider: {
36-
address: withPrefix(service.addr),
37-
name: service.name,
38-
icon: service.icon,
39-
},
40-
}
44+
return null
4145
}
4246
}

0 commit comments

Comments
 (0)