Skip to content

Commit b6d066c

Browse files
firebase send and multi-plexed auth
1 parent 5f5402d commit b6d066c

11 files changed

+1515
-34
lines changed

.vscode/settings.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
}
3333
],
3434
"cSpell.words": [
35-
"Geohash"
35+
"Geohash",
36+
"firestore"
3637
]
3738
}

package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@xyo-network/sdk-diviner-nodejs",
3-
"version": "0.7.1",
3+
"version": "0.7.2",
44
"description": "XYO Diviner SDK",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",
@@ -33,6 +33,7 @@
3333
"dist/payment/lightning/plugin/index.js",
3434
"dist/payment/plugin/index.js",
3535
"dist/payment/repository/dynammodb/plugin/index.js",
36+
"dist/payment/repository/firestore/plugin/index.js",
3637
"dist/query/plugin/query/index.js",
3738
"dist/query/plugin/query-chain-tracer/index.js",
3839
"dist/query/plugin/query-geohash/index.js",
@@ -73,6 +74,8 @@
7374
"aws-sdk": "^2.441.0",
7475
"bs58": "^4.0.1",
7576
"eth-sig-util": "1.4.2",
77+
"firebase": "^6.2.0",
78+
"firebase-admin": "^8.1.0",
7679
"graphql": "^14.2.1",
7780
"graphql-tag": "^2.10.1",
7881
"graphql-type-json": "^0.3.0",

src/payment/plugin/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class QueryPaymentPlugin implements IXyoPlugin {
2727
const creditEndpoint = new XyoCreditEndpoint(store)
2828
const spendEndpoint = new XyoSpendEndpoint(store)
2929
const scan = delegate.deps.QUERY as XyoQuery
30-
scan.auth = new XyoQueryAuth(store)
30+
scan.auth.authProviders.payment = new XyoQueryAuth(store)
3131

3232
delegate.graphql.addQuery(XyoCreditEndpoint.query)
3333
delegate.graphql.addResolver(XyoCreditEndpoint.queryName, creditEndpoint)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { IXyoAuth } from '../../../query'
2+
import { XyoCoinAuth } from './firestore-coin-spend-store'
3+
import firebaseAdmin from 'firebase-admin'
4+
5+
interface IFirestoreCoinAuthConfig {
6+
token: string
7+
}
8+
9+
export class FirestoreCoinAuth implements IXyoAuth {
10+
public name = 'firestore-coin-auth'
11+
private store: XyoCoinAuth
12+
13+
constructor (store: XyoCoinAuth) {
14+
this.store = store
15+
}
16+
17+
public async getCredits (token: string): Promise<number> {
18+
const userId = await this.getUserIdFromFirebaseToken(token)
19+
20+
if (!userId) {
21+
return 0
22+
}
23+
24+
return await this.store.getCreditsForKey(userId) || 0
25+
}
26+
27+
public async didComplete(config: any): Promise<void> {
28+
const authConfig = config.coin as IFirestoreCoinAuthConfig
29+
const userId = await this.getUserIdFromFirebaseToken(authConfig.token)
30+
31+
if (userId) {
32+
const constAmount = (await this.store.getCreditsForKey(userId) || 0)
33+
await this.store.setCreditsForKey(userId, constAmount - 1)
34+
await this.store.incrementSpentForUser(userId)
35+
return
36+
}
37+
38+
throw new Error('No user font to spend tokens')
39+
}
40+
41+
public async auth(config: any): Promise<boolean> {
42+
const authConfig = config.coin as IFirestoreCoinAuthConfig
43+
const userId = await this.getUserIdFromFirebaseToken(authConfig.token)
44+
45+
if (userId) {
46+
const canSpend = (await this.store.getCreditsForKey(userId) || 0)
47+
return canSpend > 1
48+
}
49+
50+
return false
51+
52+
}
53+
54+
private async getUserIdFromFirebaseToken (token: string): Promise<string | undefined> {
55+
const decodedToken = await firebaseAdmin.auth().verifyIdToken(token)
56+
return decodedToken.uid
57+
}
58+
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
import { IXyoPaymentStore } from '../../../payment'
3+
import { firestore } from 'firebase'
4+
5+
export class XyoCoinAuth implements IXyoPaymentStore {
6+
private firestore: firestore.Firestore
7+
8+
constructor(firestoreInstance: firestore.Firestore) {
9+
this.firestore = firestoreInstance
10+
}
11+
12+
public async getCreditsForKey(key: string): Promise<number | undefined> {
13+
const docRef = await this.firestore.collection('coin_users').doc(key).get()
14+
15+
if (!docRef.exists) {
16+
return 0
17+
}
18+
19+
const data = docRef.data()
20+
21+
if (data) {
22+
return data.xyoCollected
23+
}
24+
25+
return 0
26+
}
27+
28+
public async incrementSpentForUser(key: string): Promise<void> {
29+
const docRef = await this.firestore.collection('coin_users').doc(key).get()
30+
31+
if (!docRef.exists) {
32+
return
33+
}
34+
35+
const data = docRef.data()
36+
37+
if (!data) {
38+
return
39+
}
40+
41+
await this.firestore.collection('coin_users').doc(key).update({
42+
xyoQuerySpent: (data.xyoQuerySpent || 0) + 1.
43+
})
44+
}
45+
46+
public async setCreditsForKey(key: string, credits: number): Promise<void> {
47+
const docRef = await this.firestore.collection('coin_users').doc(key).get()
48+
49+
if (!docRef.exists) {
50+
return
51+
}
52+
53+
await this.firestore.collection('coin_users').doc(key).update({
54+
xyoCollected: credits
55+
})
56+
}
57+
58+
public spent(creditKey: string): Promise<void> {
59+
throw new Error('Method not implemented: didSpend.')
60+
}
61+
62+
public didSpend(creditKey: string): Promise<boolean> {
63+
throw new Error('Method not implemented: didSpend.')
64+
}
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { FirestoreCoinAuth } from '../firestore-coin-auth'
2+
3+
export class XyoFirestoreCreditEndpoint {
4+
public static query = 'coinCredits(token: String): Float'
5+
public static queryName = 'coinCredits'
6+
private spendStore: FirestoreCoinAuth
7+
8+
constructor(spend: FirestoreCoinAuth) {
9+
this.spendStore = spend
10+
}
11+
12+
public async resolve(obj: any, args: any): Promise<any> {
13+
return this.spendStore.getCredits(args.token)
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { IXyoPlugin, XyoPluginProviders, IXyoPluginDelegate } from '@xyo-network/sdk-base-nodejs'
2+
import { XyoQuery } from '../../../../query/xyo-query'
3+
import { XyoCoinAuth } from '../firestore-coin-spend-store'
4+
import { FirestoreCoinAuth } from '../firestore-coin-auth'
5+
import { XyoFirestoreCreditEndpoint } from './firestore-credit.endpoint'
6+
import firebaseAdmin from 'firebase-admin'
7+
import firebase from 'firebase'
8+
9+
class CoinPaymentPlugin implements IXyoPlugin {
10+
11+
public getName(): string {
12+
return 'coin-payment'
13+
}
14+
15+
public getProvides(): string[] {
16+
return []
17+
}
18+
19+
public getPluginDependencies(): string[] {
20+
return [
21+
XyoPluginProviders.QUERY
22+
]
23+
}
24+
25+
public async initialize(delegate: IXyoPluginDelegate): Promise<boolean> {
26+
firebaseAdmin.initializeApp({
27+
databaseURL: 'https://xyo-network-1522800011804.firebaseio.com',
28+
})
29+
30+
const scan = delegate.deps.QUERY as XyoQuery
31+
const firestoreDb = new XyoCoinAuth(firebaseAdmin.firestore() as any)
32+
const auth = new FirestoreCoinAuth(firestoreDb)
33+
scan.auth.authProviders.coin = auth
34+
35+
const creditEndpoint = new XyoFirestoreCreditEndpoint(auth)
36+
delegate.graphql.addQuery(XyoFirestoreCreditEndpoint.query)
37+
delegate.graphql.addResolver(XyoFirestoreCreditEndpoint.queryName, creditEndpoint)
38+
39+
return true
40+
}
41+
42+
}
43+
44+
export = new CoinPaymentPlugin()
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { IXyoAuth } from '..'
2+
3+
export class XyoMultiplexedQueryAuth implements IXyoAuth {
4+
public name = 'xyo-multiplex-auth'
5+
public authProviders: {[key: string]: IXyoAuth} = {}
6+
7+
public async auth(config: any): Promise<boolean> {
8+
const keys = Object.keys(config)
9+
10+
for (const key of keys) {
11+
const authProvider = this.authProviders[key]
12+
13+
if (authProvider) {
14+
return authProvider.auth(config)
15+
}
16+
}
17+
18+
return false
19+
}
20+
21+
public async didComplete(config: any): Promise<void> {
22+
const keys = Object.keys(config)
23+
24+
for (const key of keys) {
25+
const authProvider = this.authProviders[key]
26+
27+
if (authProvider) {
28+
await authProvider.didComplete(config)
29+
return
30+
}
31+
}
32+
33+
throw new Error('Auth not found')
34+
}
35+
36+
}

src/query/auth/xyo-query-auth.ts

+2
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ export class XyoQueryAuth implements IXyoAuth {
1616

1717
public async didComplete(config: any): Promise<void> {
1818
const authConfig = config.payment as IXyoQueryAuthConfig
19+
1920
const constAmount = (await this.store.getCreditsForKey(authConfig.apiKey) || 0)
2021
await this.store.setCreditsForKey(authConfig.apiKey, constAmount - 1)
2122
}
2223

2324
public async auth(config: any): Promise<boolean> {
2425
const authConfig = config.payment as IXyoQueryAuthConfig
26+
2527
const canSpend = (await this.store.getCreditsForKey(authConfig.apiKey) || 0)
2628

2729
if (canSpend < 1) {

src/query/xyo-query.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
import { IXyoSelecterCreator, IXyoFilterCreator, IXyoMutatorCreater, IXyoQuery, IXyoConfig, IXyoAuth } from '.'
2+
import { XyoMultiplexedQueryAuth } from './auth/xyo-query-auth-multiplex'
23

34
export class XyoQuery {
4-
public auth?: IXyoAuth
5+
public auth = new XyoMultiplexedQueryAuth()
56
private selectorCreators: Map<string, IXyoSelecterCreator> = new Map()
67
private filterCreators: Map<string, IXyoFilterCreator> = new Map()
78
private mutatorCreators: Map<string, IXyoMutatorCreater> = new Map()
89
private finishNotifiers: Map<string, (query: IXyoQuery, blocks: Buffer[]) => void> = new Map()
910

10-
constructor(auth?: IXyoAuth) {
11-
this.auth = auth
12-
}
13-
1411
public addSelector (selector: IXyoSelecterCreator) {
1512
this.selectorCreators.set(selector.name, selector)
1613
}

0 commit comments

Comments
 (0)