@towns-labs/sdk 2.0.6 → 2.0.7
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/dist/streamStateView_Members.d.ts +7 -0
- package/dist/streamStateView_Members.d.ts.map +1 -1
- package/dist/streamStateView_Members.js +19 -0
- package/dist/streamStateView_Members.js.map +1 -1
- package/dist/tests/multi_ne/gdms.test.js +50 -3
- package/dist/tests/multi_ne/gdms.test.js.map +1 -1
- package/dist/tests/multi_ne/userInboxMessage.test.js +3 -3
- package/dist/tests/multi_ne/userInboxMessage.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/tests/multi/notificationService.test.d.ts +0 -2
- package/dist/tests/multi/notificationService.test.d.ts.map +0 -1
- package/dist/tests/multi/notificationService.test.js +0 -51
- package/dist/tests/multi/notificationService.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/member-queue.test.d.ts +0 -2
- package/dist/tests/multi/sync-agent/member-queue.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/member-queue.test.js +0 -54
- package/dist/tests/multi/sync-agent/member-queue.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/member.test.d.ts +0 -2
- package/dist/tests/multi/sync-agent/member.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/member.test.js +0 -45
- package/dist/tests/multi/sync-agent/member.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/members.test.d.ts +0 -2
- package/dist/tests/multi/sync-agent/members.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/members.test.js +0 -35
- package/dist/tests/multi/sync-agent/members.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/riverConnection.test.d.ts +0 -5
- package/dist/tests/multi/sync-agent/riverConnection.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/riverConnection.test.js +0 -39
- package/dist/tests/multi/sync-agent/riverConnection.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/spaces.test.d.ts +0 -2
- package/dist/tests/multi/sync-agent/spaces.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/spaces.test.js +0 -33
- package/dist/tests/multi/sync-agent/spaces.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/streams.test.d.ts +0 -2
- package/dist/tests/multi/sync-agent/streams.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/streams.test.js +0 -27
- package/dist/tests/multi/sync-agent/streams.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/syncAgent.test.d.ts +0 -2
- package/dist/tests/multi/sync-agent/syncAgent.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/syncAgent.test.js +0 -68
- package/dist/tests/multi/sync-agent/syncAgent.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/syncAgents.test.d.ts +0 -2
- package/dist/tests/multi/sync-agent/syncAgents.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/syncAgents.test.js +0 -163
- package/dist/tests/multi/sync-agent/syncAgents.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/timeline.test.d.ts +0 -2
- package/dist/tests/multi/sync-agent/timeline.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/timeline.test.js +0 -232
- package/dist/tests/multi/sync-agent/timeline.test.js.map +0 -1
- package/dist/tests/multi/sync-agent/user.test.d.ts +0 -5
- package/dist/tests/multi/sync-agent/user.test.d.ts.map +0 -1
- package/dist/tests/multi/sync-agent/user.test.js +0 -55
- package/dist/tests/multi/sync-agent/user.test.js.map +0 -1
- package/dist/tests/multi/transactions.test.d.ts +0 -5
- package/dist/tests/multi/transactions.test.d.ts.map +0 -1
- package/dist/tests/multi/transactions.test.js +0 -153
- package/dist/tests/multi/transactions.test.js.map +0 -1
- package/dist/tests/multi/transactions_SpaceReview.test.d.ts +0 -2
- package/dist/tests/multi/transactions_SpaceReview.test.d.ts.map +0 -1
- package/dist/tests/multi/transactions_SpaceReview.test.js +0 -278
- package/dist/tests/multi/transactions_SpaceReview.test.js.map +0 -1
- package/dist/tests/multi/transactions_Tip.test.d.ts +0 -5
- package/dist/tests/multi/transactions_Tip.test.d.ts.map +0 -1
- package/dist/tests/multi/transactions_Tip.test.js +0 -379
- package/dist/tests/multi/transactions_Tip.test.js.map +0 -1
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @group with-entitlements
|
|
3
|
-
*/
|
|
4
|
-
import { bin_toHexString, dlog, dlogError } from '@towns-labs/utils';
|
|
5
|
-
import { BigNumber, ethers } from 'ethers';
|
|
6
|
-
import { ETH_ADDRESS, LocalhostWeb3Provider, } from '@towns-labs/web3';
|
|
7
|
-
import { townsEnv } from '../../townsEnv';
|
|
8
|
-
import { Bot } from '../../sync-agent/utils/bot';
|
|
9
|
-
import { waitFor, waitForValue } from '../testUtils';
|
|
10
|
-
import { makeUniqueChannelStreamId } from '../../id';
|
|
11
|
-
import { randomBytes } from '../../utils';
|
|
12
|
-
import { deepCopy } from 'ethers/lib/utils';
|
|
13
|
-
import { cloneDeep } from 'lodash-es';
|
|
14
|
-
import { RiverTimelineEvent } from '../../views/models/timelineTypes';
|
|
15
|
-
const base_log = dlog('csb:test:transactions_Tip');
|
|
16
|
-
const logError = dlogError('csb:test:transactions_Tip_error');
|
|
17
|
-
// Protocol fee for member tips is 0.5% (50 basis points)
|
|
18
|
-
const PROTOCOL_FEE_BASIS_POINTS = 50n;
|
|
19
|
-
const BASIS_POINTS_DENOMINATOR = 10000n;
|
|
20
|
-
// Helper function to calculate net tip amount after protocol fee
|
|
21
|
-
function calculateNetTipAmount(grossAmount) {
|
|
22
|
-
const fee = (grossAmount * PROTOCOL_FEE_BASIS_POINTS) / BASIS_POINTS_DENOMINATOR;
|
|
23
|
-
return grossAmount - fee;
|
|
24
|
-
}
|
|
25
|
-
describe('transactions_Tip', () => {
|
|
26
|
-
const townsConfig = townsEnv().makeTownsConfig();
|
|
27
|
-
const bobIdentity = new Bot(undefined, townsConfig);
|
|
28
|
-
const bobsOtherWallet = ethers.Wallet.createRandom();
|
|
29
|
-
const bobsOtherWalletProvider = new LocalhostWeb3Provider(townsConfig.base.rpcUrl, bobsOtherWallet);
|
|
30
|
-
const aliceIdentity = new Bot(undefined, townsConfig);
|
|
31
|
-
const alicesOtherWallet = ethers.Wallet.createRandom();
|
|
32
|
-
const chainId = townsConfig.base.chainConfig.chainId;
|
|
33
|
-
// updated once and shared between tests
|
|
34
|
-
let bob;
|
|
35
|
-
let alice;
|
|
36
|
-
let spaceId;
|
|
37
|
-
let defaultChannelId;
|
|
38
|
-
let messageId;
|
|
39
|
-
let aliceTokenId;
|
|
40
|
-
let dummyReceipt;
|
|
41
|
-
let dummyTipEvent;
|
|
42
|
-
let dummyTipEventCopy;
|
|
43
|
-
let dmChannelId;
|
|
44
|
-
beforeAll(async () => {
|
|
45
|
-
// setup once
|
|
46
|
-
const log = base_log.extend('beforeAll');
|
|
47
|
-
log('start');
|
|
48
|
-
// fund wallets
|
|
49
|
-
await Promise.all([
|
|
50
|
-
bobIdentity.fundWallet(),
|
|
51
|
-
aliceIdentity.fundWallet(),
|
|
52
|
-
bobsOtherWalletProvider.fundWallet(),
|
|
53
|
-
]);
|
|
54
|
-
bob = await bobIdentity.makeSyncAgent();
|
|
55
|
-
alice = await aliceIdentity.makeSyncAgent();
|
|
56
|
-
// start agents
|
|
57
|
-
await Promise.all([
|
|
58
|
-
bob.start(),
|
|
59
|
-
alice.start(),
|
|
60
|
-
bob.riverConnection.spaceDapp.walletLink.linkWalletToRootKey(bobIdentity.signer, bobsOtherWallet),
|
|
61
|
-
alice.riverConnection.spaceDapp.walletLink.linkWalletToRootKey(aliceIdentity.signer, alicesOtherWallet),
|
|
62
|
-
]);
|
|
63
|
-
// before they can do anything on river, they need to be in a space
|
|
64
|
-
const { spaceId: sid, defaultChannelId: cid } = await bob.spaces.createSpace({ spaceName: 'BlastOff_Tip' }, bobIdentity.signer);
|
|
65
|
-
spaceId = sid;
|
|
66
|
-
defaultChannelId = cid;
|
|
67
|
-
await alice.spaces.joinSpace(spaceId, aliceIdentity.signer);
|
|
68
|
-
const channel = alice.spaces.getSpace(spaceId).getChannel(defaultChannelId);
|
|
69
|
-
const { eventId } = await channel.sendMessage('hello bob');
|
|
70
|
-
messageId = eventId;
|
|
71
|
-
log('bob and alice joined space', spaceId, defaultChannelId, messageId);
|
|
72
|
-
const aliceTokenId_ = await bob.riverConnection.spaceDapp.getTokenIdOfOwner(spaceId, aliceIdentity.rootWallet.address);
|
|
73
|
-
expect(aliceTokenId_).toBeDefined();
|
|
74
|
-
aliceTokenId = aliceTokenId_;
|
|
75
|
-
try {
|
|
76
|
-
// dummy tip, to be used to test error cases
|
|
77
|
-
const tx = await bob.riverConnection.spaceDapp.sendTip({
|
|
78
|
-
tipParams: {
|
|
79
|
-
spaceId,
|
|
80
|
-
type: 'member',
|
|
81
|
-
tokenId: aliceTokenId,
|
|
82
|
-
currency: ETH_ADDRESS,
|
|
83
|
-
amount: 1000n,
|
|
84
|
-
messageId: messageId,
|
|
85
|
-
channelId: defaultChannelId,
|
|
86
|
-
receiver: aliceIdentity.rootWallet.address,
|
|
87
|
-
},
|
|
88
|
-
signer: bobIdentity.signer,
|
|
89
|
-
});
|
|
90
|
-
dummyReceipt = await tx.wait(2);
|
|
91
|
-
dummyTipEvent = bob.riverConnection.spaceDapp.getTipEvent(spaceId, dummyReceipt, bobIdentity.rootWallet.address);
|
|
92
|
-
}
|
|
93
|
-
catch (err) {
|
|
94
|
-
const parsedError = bob.riverConnection.spaceDapp.parseSpaceError(spaceId, err);
|
|
95
|
-
logError('parsedError', parsedError);
|
|
96
|
-
throw err;
|
|
97
|
-
}
|
|
98
|
-
expect(dummyTipEvent).toBeDefined();
|
|
99
|
-
dummyTipEventCopy = deepCopy(dummyTipEvent);
|
|
100
|
-
expect(dummyTipEventCopy).toEqual(dummyTipEvent);
|
|
101
|
-
});
|
|
102
|
-
afterEach(() => {
|
|
103
|
-
expect(dummyTipEventCopy).toEqual(dummyTipEvent); // don't modify it please, it's used for error cases
|
|
104
|
-
});
|
|
105
|
-
afterAll(async () => {
|
|
106
|
-
await bob.stop();
|
|
107
|
-
await alice.stop();
|
|
108
|
-
});
|
|
109
|
-
test('addTip', async () => {
|
|
110
|
-
// a user should be able to upload a transaction that
|
|
111
|
-
// is a tip and is valid on chain
|
|
112
|
-
const tx = await bob.riverConnection.spaceDapp.sendTip({
|
|
113
|
-
tipParams: {
|
|
114
|
-
spaceId,
|
|
115
|
-
type: 'member',
|
|
116
|
-
tokenId: aliceTokenId,
|
|
117
|
-
currency: ETH_ADDRESS,
|
|
118
|
-
amount: 1000n,
|
|
119
|
-
messageId: messageId,
|
|
120
|
-
channelId: defaultChannelId,
|
|
121
|
-
receiver: aliceIdentity.rootWallet.address,
|
|
122
|
-
},
|
|
123
|
-
signer: bobIdentity.signer,
|
|
124
|
-
});
|
|
125
|
-
const receipt = await tx.wait(2);
|
|
126
|
-
expect(receipt.from).toEqual(bobIdentity.rootWallet.address);
|
|
127
|
-
const tipEvent = bob.riverConnection.spaceDapp.getTipEvent(spaceId, receipt, bobIdentity.rootWallet.address);
|
|
128
|
-
expect(tipEvent).toBeDefined();
|
|
129
|
-
if (!tipEvent)
|
|
130
|
-
throw new Error('no tip event found');
|
|
131
|
-
await expect(bob.riverConnection.client.addTransaction_Tip(chainId, receipt, tipEvent, aliceIdentity.rootWallet.address)).resolves.not.toThrow();
|
|
132
|
-
});
|
|
133
|
-
test('bobSeesTipInUserStream', async () => {
|
|
134
|
-
// get the user "stream" that is being synced by bob
|
|
135
|
-
const stream = bob.riverConnection.client.stream(bob.riverConnection.client.userStreamId);
|
|
136
|
-
if (!stream)
|
|
137
|
-
throw new Error('no stream found');
|
|
138
|
-
const tipEvent = await waitForValue(() => {
|
|
139
|
-
const isUserBlockchainTransaction = (e) => e.content?.kind === RiverTimelineEvent.UserBlockchainTransaction;
|
|
140
|
-
const tipEvents = stream.view.timeline.filter(isUserBlockchainTransaction);
|
|
141
|
-
expect(tipEvents.length).toBeGreaterThan(0);
|
|
142
|
-
const tip = tipEvents[0];
|
|
143
|
-
// make it compile
|
|
144
|
-
if (!tip || tip.content?.kind !== RiverTimelineEvent.UserBlockchainTransaction)
|
|
145
|
-
throw new Error('no tip event found');
|
|
146
|
-
return tip.content?.transaction;
|
|
147
|
-
});
|
|
148
|
-
expect(tipEvent?.receipt).toBeDefined();
|
|
149
|
-
// the view should have been updated with the tip (net amount after 0.5% protocol fee)
|
|
150
|
-
const netTipAmount = calculateNetTipAmount(1000n);
|
|
151
|
-
expect(stream.view.userContent.tipsSent[ETH_ADDRESS]).toEqual(netTipAmount);
|
|
152
|
-
expect(stream.view.userContent.tipsSentCount[ETH_ADDRESS]).toEqual(1n);
|
|
153
|
-
expect(stream.view.userContent.tipsReceived[ETH_ADDRESS]).toEqual(undefined);
|
|
154
|
-
});
|
|
155
|
-
test('aliceSeesTipReceivedInUserStream', async () => {
|
|
156
|
-
// get the user "stream" that is being synced by alice
|
|
157
|
-
const stream = alice.riverConnection.client.stream(alice.riverConnection.client.userStreamId);
|
|
158
|
-
if (!stream)
|
|
159
|
-
throw new Error('no stream found');
|
|
160
|
-
const tipEvent = await waitForValue(() => {
|
|
161
|
-
const isUserReceivedBlockchainTransaction = (e) => e.content?.kind === RiverTimelineEvent.UserReceivedBlockchainTransaction;
|
|
162
|
-
const tipEvents = stream.view.timeline.filter(isUserReceivedBlockchainTransaction);
|
|
163
|
-
expect(tipEvents.length).toBeGreaterThan(0);
|
|
164
|
-
const tip = tipEvents[0];
|
|
165
|
-
// make it compile
|
|
166
|
-
if (!tip || tip.content?.kind !== RiverTimelineEvent.UserReceivedBlockchainTransaction)
|
|
167
|
-
throw new Error('no tip event found');
|
|
168
|
-
return tip.content;
|
|
169
|
-
});
|
|
170
|
-
if (!tipEvent)
|
|
171
|
-
throw new Error('no tip event found');
|
|
172
|
-
expect(tipEvent.receivedTransaction.transaction?.receipt).toBeDefined();
|
|
173
|
-
expect(tipEvent?.receivedTransaction.transaction?.content?.case).toEqual('tip');
|
|
174
|
-
// the view should have been updated with the tip (net amount after 0.5% protocol fee)
|
|
175
|
-
const netTipAmount = calculateNetTipAmount(1000n);
|
|
176
|
-
expect(stream.view.userContent.tipsReceived[ETH_ADDRESS]).toEqual(netTipAmount);
|
|
177
|
-
expect(stream.view.userContent.tipsReceivedCount[ETH_ADDRESS]).toEqual(1n);
|
|
178
|
-
});
|
|
179
|
-
test('bobSeesOnMessageInChannel', async () => {
|
|
180
|
-
// get the channel "stream" that is being synced by bob
|
|
181
|
-
const stream = bob.riverConnection.client.stream(defaultChannelId);
|
|
182
|
-
if (!stream)
|
|
183
|
-
throw new Error('no stream found');
|
|
184
|
-
const tipEvent = await waitForValue(() => {
|
|
185
|
-
const isTipBlockchainTransaction = (e) => e.content?.kind === RiverTimelineEvent.TipEvent;
|
|
186
|
-
const tipEvents = stream.view.timeline.filter(isTipBlockchainTransaction);
|
|
187
|
-
expect(tipEvents.length).toBeGreaterThan(0);
|
|
188
|
-
const tip = tipEvents[0];
|
|
189
|
-
// make it compile
|
|
190
|
-
if (!tip ||
|
|
191
|
-
tip.content?.kind !== RiverTimelineEvent.TipEvent ||
|
|
192
|
-
!tip.content.transaction)
|
|
193
|
-
throw new Error('no tip event found');
|
|
194
|
-
return tip.content;
|
|
195
|
-
});
|
|
196
|
-
expect(tipEvent.fromUserId).toEqual(bobIdentity.rootWallet.address);
|
|
197
|
-
const netTipAmount = calculateNetTipAmount(1000n);
|
|
198
|
-
expect(stream.view.membershipContent.tips[ETH_ADDRESS]).toEqual(netTipAmount);
|
|
199
|
-
expect(stream.view.membershipContent.tipsCount[ETH_ADDRESS]).toEqual(1n);
|
|
200
|
-
expect(stream.view.membershipContent.joined.get(bobIdentity.rootWallet.address)?.tipsSent?.[ETH_ADDRESS]).toEqual(netTipAmount);
|
|
201
|
-
expect(stream.view.membershipContent.joined.get(bobIdentity.rootWallet.address)
|
|
202
|
-
?.tipsSentCount?.[ETH_ADDRESS]).toEqual(1n);
|
|
203
|
-
});
|
|
204
|
-
test('cantAddTipWithBadChannelId', async () => {
|
|
205
|
-
const event = cloneDeep(dummyTipEvent);
|
|
206
|
-
event.channelId = makeUniqueChannelStreamId(spaceId);
|
|
207
|
-
await expect(bob.riverConnection.client.addTransaction_Tip(chainId, dummyReceipt, event, aliceIdentity.rootWallet.address, { disableTags: true })).rejects.toThrow('matching tip event not found in receipt logs');
|
|
208
|
-
});
|
|
209
|
-
test('cantAddTipWithBadMessageId', async () => {
|
|
210
|
-
const event = cloneDeep(dummyTipEvent);
|
|
211
|
-
event.messageId = bin_toHexString(randomBytes(32));
|
|
212
|
-
await expect(bob.riverConnection.client.addTransaction_Tip(chainId, dummyReceipt, event, aliceIdentity.rootWallet.address)).rejects.toThrow('matching tip event not found in receipt logs');
|
|
213
|
-
});
|
|
214
|
-
test('cantAddTipWithBadSender', async () => {
|
|
215
|
-
const event = cloneDeep(dummyTipEvent);
|
|
216
|
-
event.sender = aliceIdentity.rootWallet.address;
|
|
217
|
-
await expect(bob.riverConnection.client.addTransaction_Tip(chainId, dummyReceipt, event, aliceIdentity.rootWallet.address)).rejects.toThrow('matching tip event not found in receipt logs');
|
|
218
|
-
});
|
|
219
|
-
test('cantAddTipWithBadReceiver', async () => {
|
|
220
|
-
const event = cloneDeep(dummyTipEvent);
|
|
221
|
-
event.receiver = bobIdentity.rootWallet.address;
|
|
222
|
-
await expect(bob.riverConnection.client.addTransaction_Tip(chainId, dummyReceipt, event, aliceIdentity.rootWallet.address)).rejects.toThrow('matching tip event not found in receipt logs');
|
|
223
|
-
});
|
|
224
|
-
test('cantAddTipWithBadAmount', async () => {
|
|
225
|
-
const event = cloneDeep(dummyTipEvent);
|
|
226
|
-
event.amount = BigNumber.from(10000000n);
|
|
227
|
-
await expect(bob.riverConnection.client.addTransaction_Tip(chainId, dummyReceipt, event, aliceIdentity.rootWallet.address)).rejects.toThrow('matching tip event not found in receipt logs');
|
|
228
|
-
});
|
|
229
|
-
test('cantAddTipWithBadCurrency', async () => {
|
|
230
|
-
const event = cloneDeep(dummyTipEvent);
|
|
231
|
-
event.currency = '0x0000000000000000000000000000000000000000';
|
|
232
|
-
await expect(bob.riverConnection.client.addTransaction_Tip(chainId, dummyReceipt, event, aliceIdentity.rootWallet.address)).rejects.toThrow('matching tip event not found in receipt logs');
|
|
233
|
-
});
|
|
234
|
-
test('cantAddTipWithBadToUserAddress', async () => {
|
|
235
|
-
const event = cloneDeep(dummyTipEvent);
|
|
236
|
-
await expect(bob.riverConnection.client.addTransaction_Tip(chainId, dummyReceipt, event, bobIdentity.rootWallet.address)).rejects.toThrow('IsEntitled failed');
|
|
237
|
-
});
|
|
238
|
-
test('bobSnapshot', async () => {
|
|
239
|
-
// force a snapshot of the user "stream" that is being synced by bob
|
|
240
|
-
await bob.riverConnection.client.debugForceMakeMiniblock(bob.riverConnection.client.userStreamId, { forceSnapshot: true });
|
|
241
|
-
// refetch the stream using getStream, make sure it parses the snapshot correctly
|
|
242
|
-
const stream = await bob.riverConnection.client.getStream(bob.riverConnection.client.userStreamId);
|
|
243
|
-
const netTipAmount = calculateNetTipAmount(1000n);
|
|
244
|
-
expect(stream.userContent.tipsSent[ETH_ADDRESS]).toEqual(netTipAmount);
|
|
245
|
-
expect(stream.userContent.tipsReceived[ETH_ADDRESS]).toBeUndefined();
|
|
246
|
-
expect(stream.userContent.tipsSentCount[ETH_ADDRESS]).toEqual(1n);
|
|
247
|
-
expect(stream.userContent.tipsReceivedCount[ETH_ADDRESS]).toEqual(undefined);
|
|
248
|
-
});
|
|
249
|
-
test('aliceSnapshot', async () => {
|
|
250
|
-
// force a snapshot of the user "stream" that is being synced by alice
|
|
251
|
-
await alice.riverConnection.client.debugForceMakeMiniblock(alice.riverConnection.client.userStreamId, { forceSnapshot: true });
|
|
252
|
-
// refetch the gtream using getStream, make sure it parses the snapshot correctly
|
|
253
|
-
const stream = await alice.riverConnection.client.getStream(alice.riverConnection.client.userStreamId);
|
|
254
|
-
const netTipAmount = calculateNetTipAmount(1000n);
|
|
255
|
-
expect(stream.userContent.tipsReceived[ETH_ADDRESS]).toEqual(netTipAmount);
|
|
256
|
-
expect(stream.userContent.tipsSent[ETH_ADDRESS]).toBeUndefined();
|
|
257
|
-
expect(stream.userContent.tipsReceivedCount[ETH_ADDRESS]).toEqual(1n);
|
|
258
|
-
expect(stream.userContent.tipsSentCount[ETH_ADDRESS]).toEqual(undefined);
|
|
259
|
-
});
|
|
260
|
-
test('channelSnapshot', async () => {
|
|
261
|
-
// force a snapshot of the channel "stream" that is being synced by bob
|
|
262
|
-
await bob.riverConnection.client.debugForceMakeMiniblock(defaultChannelId, {
|
|
263
|
-
forceSnapshot: true,
|
|
264
|
-
});
|
|
265
|
-
// refetch the stream using getStream, make sure it parses the snapshot correctly
|
|
266
|
-
const stream = await bob.riverConnection.client.getStream(defaultChannelId);
|
|
267
|
-
if (!stream)
|
|
268
|
-
throw new Error('no stream found');
|
|
269
|
-
const netTipAmount = calculateNetTipAmount(1000n);
|
|
270
|
-
expect(stream.membershipContent.tips[ETH_ADDRESS]).toEqual(netTipAmount);
|
|
271
|
-
expect(stream.membershipContent.tipsCount[ETH_ADDRESS]).toEqual(1n);
|
|
272
|
-
const bobMember = stream.membershipContent.joined.get(bobIdentity.rootWallet.address);
|
|
273
|
-
const aliceMember = stream.membershipContent.joined.get(aliceIdentity.rootWallet.address);
|
|
274
|
-
expect(bobMember?.tipsSent?.[ETH_ADDRESS]).toEqual(netTipAmount);
|
|
275
|
-
expect(bobMember?.tipsSentCount?.[ETH_ADDRESS]).toEqual(1n);
|
|
276
|
-
expect(aliceMember?.tipsReceived?.[ETH_ADDRESS]).toEqual(netTipAmount);
|
|
277
|
-
expect(aliceMember?.tipsReceivedCount?.[ETH_ADDRESS]).toEqual(1n);
|
|
278
|
-
});
|
|
279
|
-
test('addSecondTip', async () => {
|
|
280
|
-
// a user should be able to upload a transaction that
|
|
281
|
-
// is a tip and is valid on chain
|
|
282
|
-
const tx = await bob.riverConnection.spaceDapp.sendTip({
|
|
283
|
-
tipParams: {
|
|
284
|
-
spaceId,
|
|
285
|
-
type: 'member',
|
|
286
|
-
tokenId: aliceTokenId,
|
|
287
|
-
currency: ETH_ADDRESS,
|
|
288
|
-
amount: 1000n,
|
|
289
|
-
messageId: messageId,
|
|
290
|
-
channelId: defaultChannelId,
|
|
291
|
-
receiver: aliceIdentity.rootWallet.address,
|
|
292
|
-
},
|
|
293
|
-
signer: bobIdentity.signer,
|
|
294
|
-
});
|
|
295
|
-
const receipt = await tx.wait(2);
|
|
296
|
-
expect(receipt.from).toEqual(bobIdentity.rootWallet.address);
|
|
297
|
-
const tipEvent = bob.riverConnection.spaceDapp.getTipEvent(spaceId, receipt, bobIdentity.rootWallet.address);
|
|
298
|
-
expect(tipEvent).toBeDefined();
|
|
299
|
-
if (!tipEvent)
|
|
300
|
-
throw new Error('no tip event found');
|
|
301
|
-
await expect(bob.riverConnection.client.addTransaction_Tip(chainId, receipt, tipEvent, aliceIdentity.rootWallet.address)).resolves.not.toThrow();
|
|
302
|
-
});
|
|
303
|
-
test('bobSeesSecondTipInUserStream', async () => {
|
|
304
|
-
// get the user "stream" that is being synced by bob
|
|
305
|
-
const stream = bob.riverConnection.client.stream(bob.riverConnection.client.userStreamId);
|
|
306
|
-
if (!stream)
|
|
307
|
-
throw new Error('no stream found');
|
|
308
|
-
// the view should have been updated with the tip (2 tips after protocol fees)
|
|
309
|
-
const totalNetTipAmount = calculateNetTipAmount(2000n);
|
|
310
|
-
await waitFor(() => {
|
|
311
|
-
expect(stream.view.userContent.tipsSent[ETH_ADDRESS]).toEqual(totalNetTipAmount);
|
|
312
|
-
expect(stream.view.userContent.tipsSentCount[ETH_ADDRESS]).toEqual(2n);
|
|
313
|
-
expect(stream.view.userContent.tipsReceived[ETH_ADDRESS]).toEqual(undefined);
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
|
-
test('aliceSeesSecondTipReceivedInUserStream', async () => {
|
|
317
|
-
// get the user "stream" that is being synced by alice
|
|
318
|
-
const stream = alice.riverConnection.client.stream(alice.riverConnection.client.userStreamId);
|
|
319
|
-
if (!stream)
|
|
320
|
-
throw new Error('no stream found');
|
|
321
|
-
// the view should have been updated with the tip (2 tips after protocol fees)
|
|
322
|
-
const totalNetTipAmount = calculateNetTipAmount(2000n);
|
|
323
|
-
await waitFor(() => {
|
|
324
|
-
expect(stream.view.userContent.tipsReceived[ETH_ADDRESS]).toEqual(totalNetTipAmount);
|
|
325
|
-
expect(stream.view.userContent.tipsReceivedCount[ETH_ADDRESS]).toEqual(2n);
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
// DM tip tests (type: 'any') - tips sent in a DM context
|
|
329
|
-
// these tips go through the AccountModules contract instead of a space's tipping contract
|
|
330
|
-
test('addDmTip', async () => {
|
|
331
|
-
const { streamId } = await bob.dms.createDM(alice.userId);
|
|
332
|
-
dmChannelId = streamId;
|
|
333
|
-
const dmChannel = bob.dms.getDm(dmChannelId);
|
|
334
|
-
await waitFor(() => expect(dmChannel.members.data.initialized).toBe(true));
|
|
335
|
-
const { eventId: dmMessageId } = await dmChannel.sendMessage('hello in DM');
|
|
336
|
-
await expect(dmChannel.sendTip(dmMessageId, {
|
|
337
|
-
receiver: aliceIdentity.rootWallet.address,
|
|
338
|
-
currency: ETH_ADDRESS,
|
|
339
|
-
amount: 500n,
|
|
340
|
-
chainId,
|
|
341
|
-
}, bobIdentity.signer)).resolves.not.toThrow();
|
|
342
|
-
// Verify the tip event appears in the DM channel's timeline
|
|
343
|
-
const stream = bob.riverConnection.client.stream(dmChannelId);
|
|
344
|
-
if (!stream)
|
|
345
|
-
throw new Error('no stream found');
|
|
346
|
-
const tipEvent = await waitForValue(() => {
|
|
347
|
-
const isTipBlockchainTransaction = (e) => e.content?.kind === RiverTimelineEvent.TipEvent;
|
|
348
|
-
const tipEvents = stream.view.timeline.filter(isTipBlockchainTransaction);
|
|
349
|
-
expect(tipEvents.length).toBeGreaterThan(0);
|
|
350
|
-
const tip = tipEvents[0];
|
|
351
|
-
if (!tip ||
|
|
352
|
-
tip.content?.kind !== RiverTimelineEvent.TipEvent ||
|
|
353
|
-
!tip.content.transaction)
|
|
354
|
-
throw new Error('no tip event found');
|
|
355
|
-
return tip.content;
|
|
356
|
-
});
|
|
357
|
-
expect(tipEvent.fromUserId).toEqual(bobIdentity.rootWallet.address);
|
|
358
|
-
});
|
|
359
|
-
test('dmChannelSnapshot', async () => {
|
|
360
|
-
// Force a snapshot of the DM channel
|
|
361
|
-
await bob.riverConnection.client.debugForceMakeMiniblock(dmChannelId, {
|
|
362
|
-
forceSnapshot: true,
|
|
363
|
-
});
|
|
364
|
-
// Refetch the stream using getStream, make sure it parses the snapshot correctly
|
|
365
|
-
const stream = await bob.riverConnection.client.getStream(dmChannelId);
|
|
366
|
-
if (!stream)
|
|
367
|
-
throw new Error('no stream found');
|
|
368
|
-
// DM tips don't have protocol fees, so the full amount should be recorded
|
|
369
|
-
expect(stream.membershipContent.tips[ETH_ADDRESS]).toEqual(500n);
|
|
370
|
-
expect(stream.membershipContent.tipsCount[ETH_ADDRESS]).toEqual(1n);
|
|
371
|
-
const bobMember = stream.membershipContent.joined.get(bobIdentity.rootWallet.address);
|
|
372
|
-
const aliceMember = stream.membershipContent.joined.get(aliceIdentity.rootWallet.address);
|
|
373
|
-
expect(bobMember?.tipsSent?.[ETH_ADDRESS]).toEqual(500n);
|
|
374
|
-
expect(bobMember?.tipsSentCount?.[ETH_ADDRESS]).toEqual(1n);
|
|
375
|
-
expect(aliceMember?.tipsReceived?.[ETH_ADDRESS]).toEqual(500n);
|
|
376
|
-
expect(aliceMember?.tipsReceivedCount?.[ETH_ADDRESS]).toEqual(1n);
|
|
377
|
-
});
|
|
378
|
-
});
|
|
379
|
-
//# sourceMappingURL=transactions_Tip.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transactions_Tip.test.js","sourceRoot":"","sources":["../../../src/tests/multi/transactions_Tip.test.ts"],"names":[],"mappings":"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"}
|