arnacon-webrtc-service 0.1.74 → 0.1.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/globalserviceconfig.json +11 -1
- package/package.json +1 -1
- package/webRTCservice/modules/blockchain.js +65 -3
- package/webRTCservice/modules/callRouter.js +20 -5
- package/webRTCservice/services/email.js +9 -3
- package/webRTCservice/services/phonemyemail.js +8 -1
- package/webRTCservice/webRTCmanager.js +9 -2
package/globalserviceconfig.json
CHANGED
|
@@ -77,7 +77,17 @@
|
|
|
77
77
|
"rpc": "https://sapphire.oasis.io",
|
|
78
78
|
"chainId": 23294,
|
|
79
79
|
"businessNumberDbAddress": "",
|
|
80
|
-
"callerIdPoolAddress": "0x903796dc34Bb9A5eD76A41bBA6C40CfebD1f4269"
|
|
80
|
+
"callerIdPoolAddress": "0x903796dc34Bb9A5eD76A41bBA6C40CfebD1f4269",
|
|
81
|
+
"businessNumberDb": {
|
|
82
|
+
"rpc": "https://sapphire.oasis.io",
|
|
83
|
+
"chainId": 23294,
|
|
84
|
+
"address": "0xFc80534F731E3849Bc06970B0e8645d72A34f493"
|
|
85
|
+
},
|
|
86
|
+
"callerIdPool": {
|
|
87
|
+
"rpc": "https://sapphire.oasis.io",
|
|
88
|
+
"chainId": 23294,
|
|
89
|
+
"address": "0x903796dc34Bb9A5eD76A41bBA6C40CfebD1f4269"
|
|
90
|
+
}
|
|
81
91
|
},
|
|
82
92
|
"messageProcessorUrl": "https://europe-west3-asterisk-tts-test.cloudfunctions.net/client_msg_processor",
|
|
83
93
|
"polygon": {
|
package/package.json
CHANGED
|
@@ -16,6 +16,8 @@ function createBlockchainApi({
|
|
|
16
16
|
const SAPPHIRE_TESTNET_RPC = config.sapphireTestnet.rpc;
|
|
17
17
|
const NFT_CALLER_ID_POOL_ADDRESS = config.sapphireTestnet.NFTCallerIdPool;
|
|
18
18
|
const ROFL_LOGIC_CONFIG = config.roflLogic || {};
|
|
19
|
+
const ROFL_BUSINESS_NUMBER_DB_CONFIG = ROFL_LOGIC_CONFIG.businessNumberDb || {};
|
|
20
|
+
const ROFL_CALLER_ID_POOL_CONFIG = ROFL_LOGIC_CONFIG.callerIdPool || {};
|
|
19
21
|
const ROFL_LOGIC_RPC =
|
|
20
22
|
process.env.ROFL_LOGIC_RPC_URL ||
|
|
21
23
|
ROFL_LOGIC_CONFIG.rpc ||
|
|
@@ -23,12 +25,36 @@ function createBlockchainApi({
|
|
|
23
25
|
SAPPHIRE_RPC;
|
|
24
26
|
const ROFL_LOGIC_CHAIN_ID =
|
|
25
27
|
Number(process.env.ROFL_LOGIC_CHAIN_ID || ROFL_LOGIC_CONFIG.chainId || 0) || undefined;
|
|
28
|
+
const ROFL_BUSINESS_NUMBER_DB_RPC =
|
|
29
|
+
process.env.ROFL_LOGIC_BUSINESS_NUMBER_DB_RPC_URL ||
|
|
30
|
+
ROFL_BUSINESS_NUMBER_DB_CONFIG.rpc ||
|
|
31
|
+
ROFL_LOGIC_RPC;
|
|
32
|
+
const ROFL_BUSINESS_NUMBER_DB_CHAIN_ID =
|
|
33
|
+
Number(
|
|
34
|
+
process.env.ROFL_LOGIC_BUSINESS_NUMBER_DB_CHAIN_ID ||
|
|
35
|
+
ROFL_BUSINESS_NUMBER_DB_CONFIG.chainId ||
|
|
36
|
+
ROFL_LOGIC_CHAIN_ID ||
|
|
37
|
+
0,
|
|
38
|
+
) || undefined;
|
|
26
39
|
const ROFL_BUSINESS_NUMBER_DB_ADDRESS =
|
|
27
40
|
process.env.ROFL_LOGIC_BUSINESS_NUMBER_DB_ADDRESS ||
|
|
41
|
+
ROFL_BUSINESS_NUMBER_DB_CONFIG.address ||
|
|
28
42
|
ROFL_LOGIC_CONFIG.businessNumberDbAddress ||
|
|
29
43
|
"";
|
|
44
|
+
const ROFL_CALLER_ID_POOL_RPC =
|
|
45
|
+
process.env.ROFL_LOGIC_CALLER_ID_POOL_RPC_URL ||
|
|
46
|
+
ROFL_CALLER_ID_POOL_CONFIG.rpc ||
|
|
47
|
+
ROFL_LOGIC_RPC;
|
|
48
|
+
const ROFL_CALLER_ID_POOL_CHAIN_ID =
|
|
49
|
+
Number(
|
|
50
|
+
process.env.ROFL_LOGIC_CALLER_ID_POOL_CHAIN_ID ||
|
|
51
|
+
ROFL_CALLER_ID_POOL_CONFIG.chainId ||
|
|
52
|
+
ROFL_LOGIC_CHAIN_ID ||
|
|
53
|
+
0,
|
|
54
|
+
) || undefined;
|
|
30
55
|
const ROFL_CALLER_ID_POOL_ADDRESS =
|
|
31
56
|
process.env.ROFL_LOGIC_CALLER_ID_POOL_ADDRESS ||
|
|
57
|
+
ROFL_CALLER_ID_POOL_CONFIG.address ||
|
|
32
58
|
ROFL_LOGIC_CONFIG.callerIdPoolAddress ||
|
|
33
59
|
NFT_CALLER_ID_POOL_ADDRESS;
|
|
34
60
|
const ROFL_PKEY = process.env.ROFL_LOGIC_PKEY || process.env.PKEY || "";
|
|
@@ -68,6 +94,8 @@ function createBlockchainApi({
|
|
|
68
94
|
let sapphireProvider = null;
|
|
69
95
|
let sapphireTestnetProvider = null;
|
|
70
96
|
let roflLogicProvider = null;
|
|
97
|
+
let businessNumberDbProvider = null;
|
|
98
|
+
let callerIdPoolProvider = null;
|
|
71
99
|
let businessNumberDbContract = null;
|
|
72
100
|
let callerIdPoolRoflContract = null;
|
|
73
101
|
let roflPoolOwnerAddress = null;
|
|
@@ -101,6 +129,34 @@ function createBlockchainApi({
|
|
|
101
129
|
return roflLogicProvider;
|
|
102
130
|
}
|
|
103
131
|
|
|
132
|
+
function getBusinessNumberDbProvider() {
|
|
133
|
+
if (!businessNumberDbProvider) {
|
|
134
|
+
if (ROFL_BUSINESS_NUMBER_DB_CHAIN_ID) {
|
|
135
|
+
businessNumberDbProvider = new ethers.providers.JsonRpcProvider(
|
|
136
|
+
ROFL_BUSINESS_NUMBER_DB_RPC,
|
|
137
|
+
ROFL_BUSINESS_NUMBER_DB_CHAIN_ID,
|
|
138
|
+
);
|
|
139
|
+
} else {
|
|
140
|
+
businessNumberDbProvider = new ethers.providers.JsonRpcProvider(ROFL_BUSINESS_NUMBER_DB_RPC);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return businessNumberDbProvider;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function getCallerIdPoolProvider() {
|
|
147
|
+
if (!callerIdPoolProvider) {
|
|
148
|
+
if (ROFL_CALLER_ID_POOL_CHAIN_ID) {
|
|
149
|
+
callerIdPoolProvider = new ethers.providers.JsonRpcProvider(
|
|
150
|
+
ROFL_CALLER_ID_POOL_RPC,
|
|
151
|
+
ROFL_CALLER_ID_POOL_CHAIN_ID,
|
|
152
|
+
);
|
|
153
|
+
} else {
|
|
154
|
+
callerIdPoolProvider = new ethers.providers.JsonRpcProvider(ROFL_CALLER_ID_POOL_RPC);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return callerIdPoolProvider;
|
|
158
|
+
}
|
|
159
|
+
|
|
104
160
|
function normalizeContractAddress(value) {
|
|
105
161
|
const normalized = String(value || "").trim();
|
|
106
162
|
if (!normalized || normalized === "0x0000000000000000000000000000000000000000") return "";
|
|
@@ -129,7 +185,7 @@ function createBlockchainApi({
|
|
|
129
185
|
if (!businessNumberDbContract) {
|
|
130
186
|
const address = normalizeContractAddress(ROFL_BUSINESS_NUMBER_DB_ADDRESS);
|
|
131
187
|
if (!address) return null;
|
|
132
|
-
businessNumberDbContract = new ethers.Contract(address, BUSINESS_NUMBER_DB_ABI,
|
|
188
|
+
businessNumberDbContract = new ethers.Contract(address, BUSINESS_NUMBER_DB_ABI, getBusinessNumberDbProvider());
|
|
133
189
|
}
|
|
134
190
|
return businessNumberDbContract;
|
|
135
191
|
}
|
|
@@ -138,7 +194,7 @@ function createBlockchainApi({
|
|
|
138
194
|
if (!callerIdPoolRoflContract) {
|
|
139
195
|
const address = normalizeContractAddress(ROFL_CALLER_ID_POOL_ADDRESS);
|
|
140
196
|
if (!address) return null;
|
|
141
|
-
callerIdPoolRoflContract = new ethers.Contract(address, CALLER_ID_POOL_ROFL_ABI,
|
|
197
|
+
callerIdPoolRoflContract = new ethers.Contract(address, CALLER_ID_POOL_ROFL_ABI, getCallerIdPoolProvider());
|
|
142
198
|
}
|
|
143
199
|
return callerIdPoolRoflContract;
|
|
144
200
|
}
|
|
@@ -398,7 +454,9 @@ function createBlockchainApi({
|
|
|
398
454
|
if (!businessName) return null;
|
|
399
455
|
try {
|
|
400
456
|
const phoneNumber = await contract.getPhoneNumber(businessName);
|
|
401
|
-
|
|
457
|
+
const result = phoneNumber && phoneNumber !== "" ? phoneNumber : null;
|
|
458
|
+
logger.log(`[ROFL_LOCAL] business lookup ${businessName} -> ${result || "no-match"}`);
|
|
459
|
+
return result;
|
|
402
460
|
} catch (err) {
|
|
403
461
|
logger.error(`[ROFL_LOCAL] find-business-number failed for ${businessName}: ${err.message}`);
|
|
404
462
|
return null;
|
|
@@ -452,7 +510,11 @@ function createBlockchainApi({
|
|
|
452
510
|
return {
|
|
453
511
|
rpc: ROFL_LOGIC_RPC || null,
|
|
454
512
|
chainId: ROFL_LOGIC_CHAIN_ID || null,
|
|
513
|
+
businessNumberDbRpc: ROFL_BUSINESS_NUMBER_DB_RPC || null,
|
|
514
|
+
businessNumberDbChainId: ROFL_BUSINESS_NUMBER_DB_CHAIN_ID || null,
|
|
455
515
|
businessNumberDbAddress: normalizeContractAddress(ROFL_BUSINESS_NUMBER_DB_ADDRESS) || null,
|
|
516
|
+
callerIdPoolRpc: ROFL_CALLER_ID_POOL_RPC || null,
|
|
517
|
+
callerIdPoolChainId: ROFL_CALLER_ID_POOL_CHAIN_ID || null,
|
|
456
518
|
callerIdPoolAddress: normalizeContractAddress(ROFL_CALLER_ID_POOL_ADDRESS) || null,
|
|
457
519
|
roflAddress: getRoflAddress() || null,
|
|
458
520
|
};
|
|
@@ -61,11 +61,19 @@ function createCallRouter({
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
const
|
|
64
|
+
function buildBusinessLookupKeys(identifier) {
|
|
65
|
+
const normalized = String(identifier || "").trim().toLowerCase().replace("@", "_");
|
|
66
|
+
if (!normalized) return [];
|
|
67
|
+
const lookups = [normalized];
|
|
66
68
|
|
|
67
|
-
if (
|
|
68
|
-
const domain =
|
|
69
|
+
if (normalized.includes("_")) {
|
|
70
|
+
const [local, domain] = normalized.split("_", 2);
|
|
71
|
+
const localParts = String(local || "").split(".").filter(Boolean);
|
|
72
|
+
for (let i = 1; i < localParts.length; i++) {
|
|
73
|
+
const localSuffix = localParts.slice(i).join(".");
|
|
74
|
+
const key = `${localSuffix}_${domain}`;
|
|
75
|
+
if (localSuffix && domain && !lookups.includes(key)) lookups.push(key);
|
|
76
|
+
}
|
|
69
77
|
if (!lookups.includes(domain)) lookups.push(domain);
|
|
70
78
|
let parts = domain;
|
|
71
79
|
while (parts.includes(".")) {
|
|
@@ -73,13 +81,20 @@ function createCallRouter({
|
|
|
73
81
|
if (!lookups.includes(parts)) lookups.push(parts);
|
|
74
82
|
}
|
|
75
83
|
} else {
|
|
76
|
-
let parts =
|
|
84
|
+
let parts = normalized;
|
|
77
85
|
while (parts.includes(".")) {
|
|
78
86
|
parts = parts.substring(0, parts.lastIndexOf("."));
|
|
79
87
|
if (!lookups.includes(parts)) lookups.push(parts);
|
|
80
88
|
}
|
|
81
89
|
}
|
|
82
90
|
|
|
91
|
+
return lookups;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function roflCascadingBusinessLookup(identifier) {
|
|
95
|
+
const lookups = buildBusinessLookupKeys(identifier);
|
|
96
|
+
if (lookups.length === 0) return null;
|
|
97
|
+
|
|
83
98
|
logger.log(`[Route] Cascading business lookup: [${lookups.join(", ")}]`);
|
|
84
99
|
|
|
85
100
|
for (const callee of lookups) {
|
|
@@ -46,8 +46,7 @@ async function resolveDestination(ctx) {
|
|
|
46
46
|
if (addr && addr !== helpers.zeroAddress) {
|
|
47
47
|
return { route: "webrtc", wallet: addr, ensName: emailEns };
|
|
48
48
|
}
|
|
49
|
-
const
|
|
50
|
-
const businessNumber = await helpers.lookupBusinessNumber(domainPart);
|
|
49
|
+
const businessNumber = await helpers.lookupBusinessNumberCascade(parsedTo.value);
|
|
51
50
|
if (businessNumber) return { route: "sbc", number: businessNumber };
|
|
52
51
|
return { route: "reject", reason: "No ENS owner and no business mapping" };
|
|
53
52
|
}
|
|
@@ -55,8 +54,15 @@ async function resolveDestination(ctx) {
|
|
|
55
54
|
if (parsedTo.type === "raw" || parsedTo.type === "unknown") {
|
|
56
55
|
const normalized = helpers.normalizePhone(parsedTo.value);
|
|
57
56
|
if (looksLikeBusinessDomain(normalized)) {
|
|
58
|
-
const businessNumber = await helpers.
|
|
57
|
+
const businessNumber = await helpers.lookupBusinessNumberCascade(normalized);
|
|
58
|
+
helpers.logRouteDecision?.({
|
|
59
|
+
serviceId: "email",
|
|
60
|
+
route: "business-domain-cascade",
|
|
61
|
+
target: normalized,
|
|
62
|
+
result: businessNumber || null,
|
|
63
|
+
});
|
|
59
64
|
if (businessNumber) return { route: "sbc", number: businessNumber };
|
|
65
|
+
return { route: "reject", reason: `No business mapping for ${normalized}` };
|
|
60
66
|
}
|
|
61
67
|
const webrtcHit = await helpers.tryInternalWebrtcLookup(normalized, helpers.getAllServiceDomains());
|
|
62
68
|
if (webrtcHit) return webrtcHit;
|
|
@@ -42,8 +42,15 @@ async function resolveDestination(ctx) {
|
|
|
42
42
|
if (parsedTo.type === "raw" || parsedTo.type === "unknown") {
|
|
43
43
|
const normalized = helpers.normalizePhone(parsedTo.value);
|
|
44
44
|
if (looksLikeBusinessDomain(normalized)) {
|
|
45
|
-
const businessNumber = await helpers.
|
|
45
|
+
const businessNumber = await helpers.lookupBusinessNumberCascade(normalized);
|
|
46
|
+
helpers.logRouteDecision?.({
|
|
47
|
+
serviceId: "phonemyemail",
|
|
48
|
+
route: "business-domain-cascade",
|
|
49
|
+
target: normalized,
|
|
50
|
+
result: businessNumber || null,
|
|
51
|
+
});
|
|
46
52
|
if (businessNumber) return { route: "sbc", number: businessNumber };
|
|
53
|
+
return { route: "reject", reason: `No business mapping for ${normalized}` };
|
|
47
54
|
}
|
|
48
55
|
const webrtcHit = await helpers.tryInternalWebrtcLookup(normalized, helpers.getAllServiceDomains());
|
|
49
56
|
if (webrtcHit) return webrtcHit;
|
|
@@ -331,8 +331,14 @@ const roflLogicInfo = blockchainApi.getRoflLogicInfo();
|
|
|
331
331
|
console.log(
|
|
332
332
|
`[ROFL] mode=${USE_LOCAL_ROFL_LOGIC ? "local_rofl_logic" : "remote_http"} ` +
|
|
333
333
|
`baseUrl=${ROFL_BASE_URL || "n/a"} rpc=${roflLogicInfo.rpc || "n/a"} ` +
|
|
334
|
-
`chainId=${roflLogicInfo.chainId || "n/a"}
|
|
335
|
-
`
|
|
334
|
+
`chainId=${roflLogicInfo.chainId || "n/a"} ` +
|
|
335
|
+
`businessDb=${roflLogicInfo.businessNumberDbAddress || "n/a"} ` +
|
|
336
|
+
`businessDbRpc=${roflLogicInfo.businessNumberDbRpc || "n/a"} ` +
|
|
337
|
+
`businessDbChainId=${roflLogicInfo.businessNumberDbChainId || "n/a"} ` +
|
|
338
|
+
`callerIdPool=${roflLogicInfo.callerIdPoolAddress || "n/a"} ` +
|
|
339
|
+
`callerIdPoolRpc=${roflLogicInfo.callerIdPoolRpc || "n/a"} ` +
|
|
340
|
+
`callerIdPoolChainId=${roflLogicInfo.callerIdPoolChainId || "n/a"} ` +
|
|
341
|
+
`roflAddress=${roflLogicInfo.roflAddress || "n/a"}`,
|
|
336
342
|
);
|
|
337
343
|
const notificationApi = createNotificationApi({
|
|
338
344
|
blockchainApi,
|
|
@@ -535,6 +541,7 @@ function getServiceHelpers(serviceRuntime) {
|
|
|
535
541
|
lookupEnsTextRecord: (...args) => blockchainApi.resolveEnsTextRecord(...args),
|
|
536
542
|
lookupNftOwnedNumber: (...args) => blockchainApi.nftGetOwnedNumber(...args),
|
|
537
543
|
lookupBusinessNumber: (...args) => callRouterApi.roflFindBusinessNumber(...args),
|
|
544
|
+
lookupBusinessNumberCascade: (...args) => callRouterApi.roflCascadingBusinessLookup(...args),
|
|
538
545
|
assignPoolFromNumber: (...args) => callRouterApi.roflAssignFromNumber(...args),
|
|
539
546
|
getProviderForDomain: (domain) => {
|
|
540
547
|
if (!domain) return null;
|